<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/BooleanPropertyCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Component;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JTable;
import org.opentcs.guing.components.properties.type.BooleanProperty;
import org.opentcs.guing.util.UserMessageHelper;

/**
 * A cell editor for boolean properties.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class BooleanPropertyCellEditor
    extends AbstractPropertyCellEditor {

  /**
   * Creates a new instance of BooleanCellEditor
   *
   * @param checkBox
   * @param umh
   */
  public BooleanPropertyCellEditor(JCheckBox checkBox, UserMessageHelper umh) {
    super(checkBox, umh);
    checkBox.setHorizontalAlignment(JCheckBox.LEFT);
  }

  @Override
  public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {

    setValue(value);
    JCheckBox checkBox = (JCheckBox) getComponent();
    checkBox.setBackground(table.getBackground());

    if (property().getValue() instanceof Boolean) {
      checkBox.setSelected((boolean) property().getValue());
    }

    return fComponent;
  }

  @Override
  public Object getCellEditorValue() {
    JCheckBox checkBox = (JCheckBox) getComponent();
    boolean newValue = checkBox.isSelected();
    property().setValue(newValue);

    if (property().getValue() instanceof Boolean) {
      markProperty();
    }

    return property();
  }

  /**
   * Return the property of this editor.
   *
   * @return The property of this editor.
   */
  protected BooleanProperty property() {
    return (BooleanProperty) fProperty;
  }

  /**
   * Creates the details dialog.
   * Always returns null, does not create a details dialog.
   * 
   * @return always returns null, does not create a details dialog.
   */
  @Override
  protected JComponent createButtonDetailsDialog() {
    return null;
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/util/I18nPlantOverviewOperating.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

/**
 * Defines application-specific constants regarding internationalization.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface I18nPlantOverviewOperating {

  /**
   * Path to the resources related to the create transport order dialog.
   */
  String CREATETO_PATH = "i18n.org.opentcs.plantoverview.operating.dialogs.createTransportOrder";
  /**
   * Path to the resources related to dockables.
   */
  String DOCKABLE_PATH = "i18n.org.opentcs.plantoverview.operating.panels.dockable";
  /**
   * Path to the resources related to the find vehicle dialog.
   */
  String FINDVEHICLE_PATH = "i18n.org.opentcs.plantoverview.operating.dialogs.findVehicle";
  /**
   * Path to the resources related to layers.
   */
  String LAYERS_PATH = "i18n.org.opentcs.plantoverview.operating.panels.layers";
  /**
   * Path to the resources related the menu bar.
   */
  String MENU_PATH = "i18n.org.opentcs.plantoverview.operating.mainMenu";
  /**
   * Path to miscellaneous resources
   */
  String MISC_PATH = "i18n.org.opentcs.plantoverview.operating.miscellaneous";
  /**
   * Path to the resources related to the peripheral job panel.
   */
  String PERIPHERALJOB_PATH = "i18n.org.opentcs.plantoverview.operating.panels.peripheralJobs";
  /**
   * Path to the resources related to the system.
   */
  String SYSTEM_PATH = "i18n.org.opentcs.plantoverview.operating.system";
  /**
   * Path to the resources related to the transport order details dialog.
   */
  String TODETAIL_PATH = "i18n.org.opentcs.plantoverview.operating.dialogs.transportOrderDetail";
  /**
   * Path to the resources related to the transportorder sequence panel.
   */
  String TO_SEQUENCE_PATH = "i18n.org.opentcs.plantoverview.operating.panels.orderSequences";
  /**
   * Path to the resources related to toolbars.
   */
  String TOOLBAR_PATH = "i18n.org.opentcs.plantoverview.operating.toolbar";
  /**
   * Path to the resources related to the transportorder panel.
   */
  String TRANSPORTORDER_PATH = "i18n.org.opentcs.plantoverview.operating.panels.transportOrders";
  /**
   * Path to the resources related to the vehicle popup.
   */
  String VEHICLEPOPUP_PATH = "i18n.org.opentcs.plantoverview.operating.dialogs.vehiclePopup";
  /**
   * Path to the resources related to the vehicle view.
   */
  String VEHICLEVIEW_PATH = "i18n.org.opentcs.plantoverview.operating.panels.vehicleView";
  /**
   * Path to the resources related to the create peripheral job panel.
   */
  String CREATE_PERIPHERAL_JOB_PATH = "i18n.org.opentcs.plantoverview.operating.dialogs.createPeripheralJob";
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/DefaultPeripheralJobDispatcher.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.components.kernel.PeripheralJobDispatcher;
import org.opentcs.components.kernel.services.InternalPeripheralJobService;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Dispatches peripheral jobs and peripheral devices represented by locations.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPeripheralJobDispatcher
    implements PeripheralJobDispatcher,
               PeripheralJobCallback {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultPeripheralJobDispatcher.class);
  /**
   * The peripheral service to use.
   */
  private final InternalPeripheralService peripheralService;
  /**
   * The peripheral job service to use.
   */
  private final InternalPeripheralJobService peripheralJobService;
  /**
   * The kernel's executor.
   */
  private final ScheduledExecutorService kernelExecutor;
  /**
   * Performs a full dispatch run.
   */
  private final FullDispatchTask fullDispatchTask;
  /**
   * A task to periodically trigger the job dispatcher.
   */
  private final Provider<PeriodicPeripheralRedispatchingTask> periodicDispatchTaskProvider;
  /**
   * The peripheral job dispatcher's configuration.
   */
  private final DefaultPeripheralJobDispatcherConfiguration configuration;
  /**
   * The future for the periodic dispatch task.
   */
  private ScheduledFuture<?> periodicDispatchTaskFuture;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param peripheralService The peripheral service to use.
   * @param peripheralJobService The peripheral job service to use.
   * @param kernelExecutor Executes dispatching tasks.
   * @param fullDispatchTask Performs a full dispatch run.
   * @param periodicDispatchTaskProvider A task to periodically trigger the job dispatcher.
   * @param configuration The peripheral job dispatcher's configuration.
   */
  @Inject
  public DefaultPeripheralJobDispatcher(
      InternalPeripheralService peripheralService,
      InternalPeripheralJobService peripheralJobService,
      @KernelExecutor ScheduledExecutorService kernelExecutor,
      FullDispatchTask fullDispatchTask,
      Provider<PeriodicPeripheralRedispatchingTask> periodicDispatchTaskProvider,
      DefaultPeripheralJobDispatcherConfiguration configuration) {
    this.peripheralService = requireNonNull(peripheralService, "peripheralService");
    this.peripheralJobService = requireNonNull(peripheralJobService, "peripheralJobService");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
    this.fullDispatchTask = requireNonNull(fullDispatchTask, "fullDispatchTask");
    this.periodicDispatchTaskProvider = requireNonNull(periodicDispatchTaskProvider,
                                                       "periodicDispatchTaskProvider");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    LOG.debug("Initializing...");
    fullDispatchTask.initialize();

    LOG.debug("Scheduling periodic peripheral job dispatch task with interval of {} ms...",
              configuration.idlePeripheralRedispatchingInterval());
    periodicDispatchTaskFuture = kernelExecutor.scheduleAtFixedRate(
        periodicDispatchTaskProvider.get(),
        configuration.idlePeripheralRedispatchingInterval(),
        configuration.idlePeripheralRedispatchingInterval(),
        TimeUnit.MILLISECONDS
    );

    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    LOG.debug("Terminating...");

    periodicDispatchTaskFuture.cancel(false);
    periodicDispatchTaskFuture = null;

    fullDispatchTask.terminate();

    initialized = false;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void dispatch() {
    LOG.debug("Scheduling dispatch task...");
    // Schedule this to be executed by the kernel executor.
    kernelExecutor.submit(fullDispatchTask);
  }

  @Override
  public void withdrawJob(Location location) {
    requireNonNull(location, "location");
    checkState(isInitialized(), "Not initialized");

    // Schedule this to be executed by the kernel executor.
    kernelExecutor.submit(() -> {
      LOG.debug("Scheduling withdrawal for location '{}'...", location.getName());

      // TODO Abort peripheral job
    });
  }

  @Override
  public void peripheralJobFinished(PeripheralJob job) {
    kernelExecutor.submit(() -> {
      peripheralJobService.updatePeripheralJobState(job.getReference(),
                                                    PeripheralJob.State.FINISHED);
      peripheralService.updatePeripheralProcState(job.getPeripheralOperation().getLocation(),
                                                  PeripheralInformation.ProcState.IDLE);
      peripheralService.updatePeripheralJob(job.getPeripheralOperation().getLocation(),
                                            null);
      dispatch();
    });
  }

  @Override
  public void peripheralJobFailed(PeripheralJob job) {
    kernelExecutor.submit(() -> {
      peripheralJobService.updatePeripheralJobState(job.getReference(),
                                                    PeripheralJob.State.FAILED);
      peripheralService.updatePeripheralProcState(job.getPeripheralOperation().getLocation(),
                                                  PeripheralInformation.ProcState.IDLE);
      peripheralService.updatePeripheralJob(job.getPeripheralOperation().getLocation(),
                                            null);
      dispatch();
    });
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/CyclicTask.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import static org.opentcs.util.Assertions.checkInRange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A template for cyclic tasks.
 * Subclasses only need to provide an implementation of
 * <code>runActualTask()</code>, which will be called until the task is
 * terminated by calling <code>terminate()</code>; after each call of
 * <code>runActualTask()</code>, a configurable delay may be inserted.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class CyclicTask
    implements Runnable {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(CyclicTask.class);
  /**
   * The time (in ms) that this task sleeps after each execution of
   * <code>runActualTask()</code>.
   */
  private final long sleepTime;
  /**
   * A private object to safely synchronize on.
   */
  private final Object syncObject = new Object();
  /**
   * The thread executing this task.
   */
  private volatile Thread taskThread;
  /**
   * This task's <em>terminated</em> flag.
   */
  private volatile boolean terminated;
  /**
   * Whether this task ignores interrupts occurring while sleeping between
   * executions of the actual task.
   */
  private volatile boolean ignoringInterrupts;

  /**
   * Creates a new CyclicTask.
   *
   * @param tSleep The time to sleep between two executions of the actual
   * task (in milliseconds).
   */
  public CyclicTask(final long tSleep) {
    this.sleepTime = checkInRange(tSleep, 0, Long.MAX_VALUE, "tSleep");
  }

  /**
   * Indicates whether this task has been terminated.
   *
   * @return <code>true</code> if, and only if, this task's
   * <em>terminated</em> flag has been set.
   */
  public boolean isTerminated() {
    return terminated;
  }

  /**
   * Terminates this task before its next execution cycle.
   * This method merely flags the task for termination and returns immediately.
   * If the actual task is currently being executed, its execution will not be
   * interrupted, but it will not be run again after finishing.
   */
  public void terminate() {
    synchronized (syncObject) {
      if (isTerminated()) {
        LOG.warn("Already terminated");
      }

      terminated = true;
      syncObject.notify();
    }
  }

  /**
   * Terminates this task before its next execution cycle and waits for it to
   * finish before returning.
   * (This method waits for termination unless the calling thread is the thread
   * that is executing this task. In that case, this method merely flags this
   * task for termination and returns immediately.)
   */
  public void terminateAndWait() {
    Thread joinThread;

    synchronized (syncObject) {
      if (isTerminated()) {
        LOG.warn("Already terminated");
        return;
      }
      else {
        joinThread = taskThread;
        terminated = true;
        syncObject.notify();
      }
    }
    // Wait for the executing thread to finish - unless the end of
    // execution had already been reached or the executing thread is terminating
    // this task itself. (In the latter case, we would wait forever for the
    // join() to return.)
    if (joinThread != null && joinThread != Thread.currentThread()) {
      try {
        joinThread.join();
      }
      catch (InterruptedException exc) {
        throw new IllegalStateException("Unexpectedly interrupted", exc);
      }
    }
  }

  /**
   * Indicates whether this task is ignoring interrupts while it's sleeping.
   *
   * @return <code>true</code> if, and only if, this task is ignoring interrupts
   * while it's sleeping.
   */
  public boolean isIgnoringInterrupts() {
    return ignoringInterrupts;
  }

  /**
   * Sets/unsets this task's flag for ignoring interrupts during sleep phases.
   *
   * @param ignoreInterrupts If <code>true</code>, this task will ignore
   * interrupts during sleep phases; if <code>false</code>, the
   * <code>run()</code> method will throw an exception when interrupted.
   */
  public void setIgnoringInterrupts(boolean ignoreInterrupts) {
    ignoringInterrupts = ignoreInterrupts;
  }

  @Override
  public void run() {
    LOG.debug("method entry");
    // Save the executing thread for use in terminateAndWait().
    taskThread = Thread.currentThread();
    // Execute the actual task until terminated.
    while (!isTerminated()) {
      LOG.debug("Running actual task...");
      runActualTask();
      // Only sleep if this task is not terminated and the sleep time is not 0.
      if (!isTerminated() && sleepTime > 0) {
        synchronized (syncObject) {
          try {
            syncObject.wait(sleepTime);
          }
          catch (InterruptedException exc) {
            if (!isIgnoringInterrupts() || isTerminated()) {
              LOG.error("Unexpectedly interrupted", exc);
              throw new IllegalStateException("Unexpectedly interrupted", exc);
            }
          }
        }
      }
    }
    // Unset taskThread again - this should prevent problems with join()ing
    // threads (in terminateAndWait()) that execute more than one task
    // subsequently.
    taskThread = null;
    LOG.debug("end of method");
  }

  /**
   * Defines the actual work this task should do in every cycle.
   */
  protected abstract void runActualTask();
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/CompositeTransportOrderSelectionFilterTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.*;
import static org.junit.Assert.*;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.selection.TransportOrderSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.orders.CompositeTransportOrderSelectionFilter;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeTransportOrderSelectionFilterTest {

  /**
   * The class to test.
   */
  private CompositeTransportOrderSelectionFilter transportOrderSelectionFilter;

  private List<TransportOrder> transportOrders;

  private static final String NAME_TRANSPORT = "Transport";
  private static final String NAME_ORDER = "Order";
  private static final String NAME_TRANSPORT_ORDER = "TransportOrder";
  private static final String NAME_RANDOM = "SomeRandomName";

  public CompositeTransportOrderSelectionFilterTest() {
  }

  @Before
  public void setUp() {
    transportOrders = new ArrayList<>();
    transportOrders.add(createTransportOrder(NAME_TRANSPORT));
    transportOrders.add(createTransportOrder(NAME_ORDER));
    transportOrders.add(createTransportOrder(NAME_TRANSPORT_ORDER));
    transportOrders.add(createTransportOrder(NAME_RANDOM));
  }

  @Test
  public void shouldFilterNoTransportOrders() {
    Set<TransportOrderSelectionFilter> filters
        = new HashSet<>(Arrays.asList(new RefuseAllFilter(),
                                      new FilterIfTransportOrderNameContainsTransport(),
                                      new FilterIfTransportOrderNameContainsOrder()));
    transportOrderSelectionFilter = new CompositeTransportOrderSelectionFilter(filters);

    long remainingTransportOrders = transportOrders.stream()
        .filter(order -> transportOrderSelectionFilter.apply(order).isEmpty())
        .count();

    assertEquals(0, remainingTransportOrders);
  }

  @Test
  public void shouldFilterTransportOrdersContainingTransport() {
    Set<TransportOrderSelectionFilter> filters
        = new HashSet<>(Arrays.asList(new FilterIfTransportOrderNameContainsTransport()));
    transportOrderSelectionFilter = new CompositeTransportOrderSelectionFilter(filters);

    long remainingTransportOrders = transportOrders.stream()
        .filter(order -> transportOrderSelectionFilter.apply(order).isEmpty())
        .count();

    assertEquals(2, remainingTransportOrders);
  }

  @Test
  public void shouldFilterTransportOrdersContainingOrder() {
    Set<TransportOrderSelectionFilter> filters
        = new HashSet<>(Arrays.asList(new FilterIfTransportOrderNameContainsOrder()));
    transportOrderSelectionFilter = new CompositeTransportOrderSelectionFilter(filters);

    long remainingTransportOrders = transportOrders.stream()
        .filter(order -> transportOrderSelectionFilter.apply(order).isEmpty())
        .count();

    assertEquals(2, remainingTransportOrders);
  }

  @Test
  public void shouldFilterTransportOrdersContainingTransportOrOrder() {
    Set<TransportOrderSelectionFilter> filters
        = new HashSet<>(Arrays.asList(new FilterIfTransportOrderNameContainsTransport(),
                                      new FilterIfTransportOrderNameContainsOrder()));
    transportOrderSelectionFilter = new CompositeTransportOrderSelectionFilter(filters);

    List<TransportOrder> remainingTransportOrders = transportOrders.stream()
        .filter(order -> !transportOrderSelectionFilter.apply(order).isEmpty())
        .collect(Collectors.toList());

    assertEquals(3, remainingTransportOrders.size());
  }

  private TransportOrder createTransportOrder(String name) {
    return new TransportOrder(name, new ArrayList<>());
  }

  private class RefuseAllFilter
      implements TransportOrderSelectionFilter {

    @Override
    public Collection<String> apply(TransportOrder t) {
      return Arrays.asList("just no");
    }
  }

  private class FilterIfTransportOrderNameContainsTransport
      implements TransportOrderSelectionFilter {

    @Override
    public Collection<String> apply(TransportOrder t) {
      return t.getName().contains("Transport")
          ? new ArrayList<>()
          : Arrays.asList("order name does not contain 'Transport'");
    }
  }

  private class FilterIfTransportOrderNameContainsOrder
      implements TransportOrderSelectionFilter {

    @Override
    public Collection<String> apply(TransportOrder t) {
      return t.getName().contains("Order")
          ? new ArrayList<>()
          : Arrays.asList("order name does not contain 'Order'");
    }
  }

}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/components/properties/PropertiesInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.multibindings.MapBinder;
import javax.inject.Singleton;
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.panel.KeyValuePropertyEditorPanel;
import org.opentcs.guing.components.properties.panel.KeyValueSetPropertyViewerEditorPanel;
import org.opentcs.guing.components.properties.panel.LinkActionsEditorPanel;
import org.opentcs.guing.components.properties.panel.ResourcePropertyViewerEditorPanel;
import org.opentcs.guing.components.properties.panel.LocationTypeActionsEditorPanel;
import org.opentcs.guing.components.properties.panel.OrderTypesPropertyEditorPanel;
import org.opentcs.guing.components.properties.panel.PropertiesPanelFactory;
import org.opentcs.guing.components.properties.panel.SymbolPropertyEditorPanel;
import org.opentcs.guing.components.properties.table.CellEditorFactory;
import org.opentcs.guing.components.properties.type.AbstractComplexProperty;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.LinkActionsProperty;
import org.opentcs.guing.components.properties.type.ResourceProperty;
import org.opentcs.guing.components.properties.type.LocationTypeActionsProperty;
import org.opentcs.guing.components.properties.type.OrderTypesProperty;
import org.opentcs.guing.components.properties.type.SymbolProperty;

/**
 * A Guice module for this package.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PropertiesInjectionModule
    extends PlantOverviewInjectionModule {

  @Override
  protected void configure() {

    install(new FactoryModuleBuilder().build(PropertiesPanelFactory.class));
    install(new FactoryModuleBuilder().build(CellEditorFactory.class));
    install(new FactoryModuleBuilder().build(PropertiesComponentsFactory.class));

    MapBinder<Class<? extends AbstractComplexProperty>, DetailsDialogContent> dialogContentMapBinder
        = MapBinder.newMapBinder(binder(),
                                 new TypeLiteral<Class<? extends AbstractComplexProperty>>() {
                             },
                                 new TypeLiteral<DetailsDialogContent>() {
                             });
    dialogContentMapBinder
        .addBinding(KeyValueProperty.class)
        .to(KeyValuePropertyEditorPanel.class);
    dialogContentMapBinder
        .addBinding(KeyValueSetProperty.class)
        .to(KeyValueSetPropertyViewerEditorPanel.class);
    dialogContentMapBinder
        .addBinding(LocationTypeActionsProperty.class)
        .to(LocationTypeActionsEditorPanel.class);
    dialogContentMapBinder
        .addBinding(LinkActionsProperty.class)
        .to(LinkActionsEditorPanel.class);
    dialogContentMapBinder
        .addBinding(SymbolProperty.class)
        .to(SymbolPropertyEditorPanel.class);
    dialogContentMapBinder
        .addBinding(OrderTypesProperty.class)
        .to(OrderTypesPropertyEditorPanel.class);
    dialogContentMapBinder
        .addBinding(ResourceProperty.class)
        .to(ResourcePropertyViewerEditorPanel.class);

    bind(SelectionPropertiesComponent.class)
        .in(Singleton.class);

  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/package-info.java<|end_filename|>
/**
 * A collection of classes providing miscellaneous functions that are used
 * throughout openTCS.
 */
package org.opentcs.util;


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/AdapterPanelComponentsFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle;

import org.opentcs.components.kernel.services.VehicleService;

/**
 * A factory for creating various comm adapter panel specific instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface AdapterPanelComponentsFactory {

  /**
   * Creates a {@link LoopbackCommAdapterPanel} representing the given process model's content.
   *
   * @param processModel The process model to represent.
   * @param vehicleService The vehicle service used for interaction with the comm adapter.
   * @return The comm adapter panel.
   */
  LoopbackCommAdapterPanel createPanel(LoopbackVehicleModelTO processModel,
                                       VehicleService vehicleService);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/management/PeripheralAttachmentInformation.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals.management;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;

/**
 * Describes which communication adapter a location is currently associated with.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralAttachmentInformation
    implements Serializable {

  /**
   * The location this attachment information belongs to.
   */
  private final TCSResourceReference<Location> locationReference;
  /**
   * The comm adapter attached to the referenced location.
   */
  private final PeripheralCommAdapterDescription attachedCommAdapter;

  /**
   * Creates a new instance.
   *
   * @param locationReference The location this attachment information belongs to.
   * @param attachedCommAdapter The comm adapter attached to the referenced location.
   */
  public PeripheralAttachmentInformation(
      @Nonnull TCSResourceReference<Location> locationReference,
      @Nonnull PeripheralCommAdapterDescription attachedCommAdapter) {
    this.locationReference = requireNonNull(locationReference, "locationReference");
    this.attachedCommAdapter = requireNonNull(attachedCommAdapter, "attachedCommAdapter");
  }

  /**
   * Returns the location this attachment information belongs to.
   *
   * @return The location this attachment information belongs to.
   */
  @Nonnull
  public TCSResourceReference<Location> getLocationReference() {
    return locationReference;
  }

  /**
   * Creates a copy of this object with the given location reference.
   *
   * @param locationReference The new location reference.
   * @return A copy of this object, differing in the given location reference.
   */
  public PeripheralAttachmentInformation withLocationReference(
      TCSResourceReference<Location> locationReference) {
    return new PeripheralAttachmentInformation(locationReference, attachedCommAdapter);
  }

  /**
   * Returns the comm adapter attached to the referenced location.
   *
   * @return The comm adapter attached to the referenced location.
   */
  @Nonnull
  public PeripheralCommAdapterDescription getAttachedCommAdapter() {
    return attachedCommAdapter;
  }

  /**
   * Creates a copy of this object with the given attached comm adapter.
   *
   * @param attachedCommAdapter The new attached comm adapter.
   * @return A copy of this object, differing in the given attached comm adapter.
   */
  public PeripheralAttachmentInformation withAttachedCommAdapter(
      @Nonnull PeripheralCommAdapterDescription attachedCommAdapter) {
    return new PeripheralAttachmentInformation(locationReference, attachedCommAdapter);
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/package-info.java<|end_filename|>
/**
 * A plugin panel providing a basic load generator.
 */
package org.opentcs.guing.plugins.panels.loadgenerator;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/DrawingOptions.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

/**
 * Allows the configuration of drawing options.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DrawingOptions {

  /**
   * Indicates whether blocks should be drawn or not.
   */
  private boolean blocksVisible = true;

  public DrawingOptions() {
  }

  /**
   * Returns whether blocks should be drawn or not.
   *
   * @return {@code true}, if blocks should be drawn, otherwise {@code false}.
   */
  public boolean isBlocksVisible() {
    return blocksVisible;
  }

  /**
   * Sets whether blocks should be drawn or not.
   *
   * @param blocksVisible The new value.
   */
  public void setBlocksVisible(boolean blocksVisible) {
    this.blocksVisible = blocksVisible;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/Assertions.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import javax.annotation.Nullable;

/**
 * Utility methods for checking preconditions, postconditions etc..
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Assertions {

  /**
   * Prevents instatiation.
   */
  private Assertions() {
  }

  /**
   * Ensures the given expression is {@code true}.
   *
   * @param expression The expression to be checked.
   * @param errorMessage An optional error message.
   * @throws IllegalArgumentException If the given expression is not true.
   */
  public static void checkArgument(boolean expression, String errorMessage)
      throws IllegalArgumentException {
    checkArgument(expression, errorMessage, (Object) null);
  }

  /**
   * Ensures the given expression is {@code true}.
   *
   * @param expression The expression to be checked.
   * @param messageTemplate A formatting template for the error message.
   * @param messageArgs The arguments to be formatted into the message template.
   * @throws IllegalArgumentException If the given expression is not true.
   */
  public static void checkArgument(boolean expression,
                                   String messageTemplate,
                                   @Nullable Object... messageArgs)
      throws IllegalArgumentException {
    if (!expression) {
      throw new IllegalArgumentException(String.format(String.valueOf(messageTemplate),
                                                       messageArgs));
    }
  }

  /**
   * Ensures the given expression is {@code true}.
   *
   * @param expression The expression to be checked.
   * @param errorMessage An optional error message.
   * @throws IllegalStateException If the given expression is not true.
   */
  public static void checkState(boolean expression, String errorMessage)
      throws IllegalStateException {
    checkState(expression, errorMessage, (Object) null);
  }

  /**
   * Ensures the given expression is {@code true}.
   *
   * @param expression The expression to be checked.
   * @param messageTemplate A formatting template for the error message.
   * @param messageArgs The arguments to be formatted into the message template.
   * @throws IllegalStateException If the given expression is not true.
   */
  public static void checkState(boolean expression,
                                String messageTemplate,
                                @Nullable Object... messageArgs)
      throws IllegalStateException {
    if (!expression) {
      throw new IllegalStateException(String.format(String.valueOf(messageTemplate),
                                                    messageArgs));
    }
  }

  /**
   * Ensures that {@code value} is not smaller than {@code minimum} and not greater than
   * {@code maximum}.
   *
   * @param value The value to be checked.
   * @param minimum The minimum value.
   * @param maximum The maximum value.
   * @return The given value.
   * @throws IllegalArgumentException If value is not within the given range.
   */
  public static int checkInRange(int value, int minimum, int maximum)
      throws IllegalArgumentException {
    return checkInRange(value, minimum, maximum, "value");
  }

  /**
   * Ensures that {@code value} is not smaller than {@code minimum} and not greater than
   * {@code maximum}.
   *
   * @param value The value to be checked.
   * @param minimum The minimum value.
   * @param maximum The maximum value.
   * @param valueName An optional name for the value to be used for the exception message.
   * @return The given value.
   * @throws IllegalArgumentException If value is not within the given range.
   */
  public static int checkInRange(int value, int minimum, int maximum, String valueName)
      throws IllegalArgumentException {
    if (value < minimum || value > maximum) {
      throw new IllegalArgumentException(String.format("%s is not in [%d..%d]: %d",
                                                       String.valueOf(valueName),
                                                       minimum,
                                                       maximum,
                                                       value));
    }
    return value;
  }

  /**
   * Ensures that {@code value} is not smaller than {@code minimum} and not greater than
   * {@code maximum}.
   *
   * @param value The value to be checked.
   * @param minimum The minimum value.
   * @param maximum The maximum value.
   * @return The given value.
   * @throws IllegalArgumentException If value is not within the given range.
   */
  public static long checkInRange(long value, long minimum, long maximum)
      throws IllegalArgumentException {
    return checkInRange(value, minimum, maximum, "value");
  }

  /**
   * Ensures that {@code value} is not smaller than {@code minimum} and not greater than
   * {@code maximum}.
   *
   * @param value The value to be checked.
   * @param minimum The minimum value.
   * @param maximum The maximum value.
   * @param valueName An optional name for the value to be used for the exception message.
   * @return The given value.
   * @throws IllegalArgumentException If value is not within the given range.
   */
  public static long checkInRange(long value, long minimum, long maximum, String valueName)
      throws IllegalArgumentException {
    if (value < minimum || value > maximum) {
      throw new IllegalArgumentException(String.format("%s is not in [%d..%d]: %d",
                                                       String.valueOf(valueName),
                                                       minimum,
                                                       maximum,
                                                       value));
    }
    return value;
  }
}


<|start_filename|>openTCS-ModelEditor/src/guiceConfig/java/org/opentcs/guing/components/drawing/DrawingInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import javax.inject.Singleton;
import org.jhotdraw.draw.DrawingEditor;
import org.opentcs.guing.components.drawing.figures.FigureFactory;
import org.opentcs.thirdparty.jhotdraw.components.drawing.OpenTCSDrawingViewModeling;

/**
 * A Guice module for this package.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DrawingInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {
    install(new FactoryModuleBuilder().build(FigureFactory.class));

    bind(OpenTCSDrawingEditor.class).in(Singleton.class);
    bind(DrawingEditor.class).to(OpenTCSDrawingEditor.class);
    
    bind(OpenTCSDrawingView.class).to(OpenTCSDrawingViewModeling.class);
    
    bind(DrawingOptions.class).in(Singleton.class);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/TCSFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.jhotdraw.draw.AbstractAttributedDecoratedFigure;
import org.jhotdraw.geom.Geom;
import org.opentcs.guing.components.drawing.ZoomPoint;
import org.opentcs.guing.model.DrawnModelComponent;
import org.opentcs.guing.model.ModelComponent;

/**
 * Base implementation for figures.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class TCSFigure
    extends AbstractAttributedDecoratedFigure
    implements ModelBasedFigure {

  /**
   * The enclosing rectangle.
   */
  protected Rectangle fDisplayBox;
  /**
   * The exact position for the middle of the figure.
   */
  protected ZoomPoint fZoomPoint;

  /**
   * Creates a new instance.
   *
   * @param modelComponent The model corresponding to this graphical object.
   */
  public TCSFigure(ModelComponent modelComponent) {
    super();
    set(FigureConstants.MODEL, modelComponent);
  }

  /**
   * Returns the exact point at the middle of the figure.
   *
   * @return the exact point at the middle of the figure.
   */
  public ZoomPoint getZoomPoint() {
    return fZoomPoint;
  }

  /**
   * Sets the zoom point.
   *
   * @param zoomPoint The point at the middle of the figure.
   */
  public void setZoomPoint(ZoomPoint zoomPoint) {
    fZoomPoint = zoomPoint;
  }

  /**
   * Clones this figure, also clones the associated model component.
   *
   * @return
   */
  @Override  // AbstractAttributedDecoratedFigure
  public TCSFigure clone() {
    try {
      TCSFigure that = (TCSFigure) super.clone();
      that.fDisplayBox = new Rectangle(fDisplayBox);
      that.setModel(getModel().clone());

      return that;
    }
    catch (CloneNotSupportedException ex) {
      throw new Error("Cannot clone() unexpectedly", ex);
    }
  }

  @Override
  protected Rectangle2D.Double getFigureDrawingArea() {
    // Add some margin to the drawing area of the figure, so the 
    // drawing area scrolls a little earlier
    Rectangle2D.Double drawingArea = super.getFigureDrawingArea();
    // if we add these two lines the Drawing becomes grey, if we start
    // the application in operating mode..
//    drawingArea.height += 50;
//    drawingArea.width += 100;

    return drawingArea;
  }

  @Override
  public DrawnModelComponent getModel() {
    return (DrawnModelComponent) get(FigureConstants.MODEL);
  }

  public void setModel(ModelComponent model) {
    set(FigureConstants.MODEL, model);
  }

  /**
   * Returns the enclosing rectangle.
   *
   * @return The enclosing rectangle.
   */
  public Rectangle displayBox() {
    return new Rectangle(fDisplayBox);
  }

  @Override
  public boolean figureContains(Point2D.Double p) {
    Rectangle2D.Double r2d = getBounds();
    // Grow for connectors
    Geom.grow(r2d, 10d, 10d);

    return (r2d.contains(p));
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/DrawingViewScrollPane.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.EventObject;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.swing.BorderFactory;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JViewport;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
import org.jhotdraw.gui.PlacardScrollPaneLayout;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.drawing.course.OriginChangeListener;

/**
 * A custom scroll pane to wrap an <code>OpenTCSDrawingView</code>.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DrawingViewScrollPane
    extends JScrollPane
    implements OriginChangeListener {

  /**
   * The drawing view.
   */
  private final OpenTCSDrawingView drawingView;
  /**
   * The view's placard panel.
   */
  private final DrawingViewPlacardPanel placardPanel;
  /**
   * Whether the rulers are currently visible or not.
   */
  private boolean rulersVisible = true;
  private Origin origin = new Origin();

  /**
   * Creates a new instance.
   *
   * @param drawingView The drawing view.
   * @param placardPanel The view's placard panel.
   */
  public DrawingViewScrollPane(OpenTCSDrawingView drawingView,
                               DrawingViewPlacardPanel placardPanel) {
    this.drawingView = requireNonNull(drawingView, "drawingView");
    this.placardPanel = requireNonNull(placardPanel, "placardPanel");

    setViewport(new JViewport());
    getViewport().setView(drawingView.getComponent());
    setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
    setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    setViewportBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
    setHorizontalScrollBar(new PlacardScrollbar());
    setLayout(new PlacardScrollPaneLayout());
    setBorder(new EmptyBorder(0, 0, 0, 0));

    // Horizontal and vertical rulers
    Ruler.Horizontal newHorizontalRuler = new Ruler.Horizontal(drawingView);
    drawingView.addPropertyChangeListener(newHorizontalRuler);
    newHorizontalRuler.setPreferredWidth(drawingView.getComponent().getWidth());
    Ruler.Vertical newVerticalRuler = new Ruler.Vertical(drawingView);
    drawingView.addPropertyChangeListener(newVerticalRuler);
    newVerticalRuler.setPreferredHeight(drawingView.getComponent().getHeight());
    setColumnHeaderView(newHorizontalRuler);
    setRowHeaderView(newVerticalRuler);

    this.add(placardPanel, JScrollPane.LOWER_LEFT_CORNER);

    // Register handler for rulers toggle button.
    placardPanel.getToggleRulersButton().addItemListener(
        new RulersToggleListener(placardPanel.getToggleRulersButton()));
    placardPanel.getToggleRulersButton().setSelected(rulersVisible);
  }

  public OpenTCSDrawingView getDrawingView() {
    return drawingView;
  }

  public DrawingViewPlacardPanel getPlacardPanel() {
    return placardPanel;
  }

  public Ruler.Horizontal getHorizontalRuler() {
    return (Ruler.Horizontal) getColumnHeader().getView();
  }

  public Ruler.Vertical getVerticalRuler() {
    return (Ruler.Vertical) getRowHeader().getView();
  }

  public boolean isRulersVisible() {
    return rulersVisible;
  }

  public void setRulersVisible(boolean visible) {
    this.rulersVisible = visible;
    if (visible) {
      getHorizontalRuler().setVisible(true);
      getHorizontalRuler().setPreferredWidth(getWidth());
      getVerticalRuler().setVisible(true);
      getVerticalRuler().setPreferredHeight(getHeight());
      getPlacardPanel().getToggleRulersButton().setSelected(true);
    }
    else {
      getHorizontalRuler().setVisible(false);
      getHorizontalRuler().setPreferredSize(new Dimension(0, 0));
      getVerticalRuler().setVisible(false);
      getVerticalRuler().setPreferredSize(new Dimension(0, 0));
      getPlacardPanel().getToggleRulersButton().setSelected(false);
    }
  }

  public void originChanged(@Nonnull Origin origin) {
    requireNonNull(origin, "origin");
    if (origin == this.origin) {
      return;
    }

    this.origin.removeListener(getHorizontalRuler());
    this.origin.removeListener(getVerticalRuler());
    this.origin.removeListener(this);
    this.origin = origin;

    origin.addListener(getHorizontalRuler());
    origin.addListener(getVerticalRuler());
    origin.addListener(this);

    // Notify the rulers directly. This is necessary to initialize/update the rulers scale when a 
    // model is created or loaded.
    // Calling origin.notifyScaleChanged() would lead to all model elements being notified (loading
    // times for bigger models would suffer).
    getHorizontalRuler().originScaleChanged(new EventObject(origin));
    getVerticalRuler().originScaleChanged(new EventObject(origin));
  }

  @Override
  public void originLocationChanged(EventObject evt) {

  }

  @Override
  public void originScaleChanged(EventObject evt) {
    drawingView.getComponent().revalidate();
  }

  private class PlacardScrollbar
      extends JScrollBar {

    public PlacardScrollbar() {
      super(JScrollBar.HORIZONTAL);
      setPreferredSize(new Dimension(100, 18));
    }
  }

  private class RulersToggleListener
      implements ItemListener {

    private final JToggleButton rulersButton;

    public RulersToggleListener(JToggleButton rulersButton) {
      this.rulersButton = requireNonNull(rulersButton, "rulersButton");
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
      setRulersVisible(rulersButton.isSelected());
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/AbstractParkingPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.Arrays;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import org.opentcs.access.to.order.DestinationCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The base class for parking phases.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractParkingPhase
    implements Phase {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AbstractParkingPhase.class);
  /**
   * The transport order service.
   */
  private final InternalTransportOrderService orderService;
  /**
   * The strategy used for finding suitable parking positions.
   */
  private final ParkingPositionSupplier parkingPosSupplier;
  /**
   * The Router instance calculating route costs.
   */
  private final Router router;
  /**
   * A collection of predicates for filtering assignment candidates.
   */
  private final CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter;
  /**
   * Provides service functions for working with transport orders.
   */
  private final TransportOrderUtil transportOrderUtil;
  /**
   * The dispatcher configuration.
   */
  private final DefaultDispatcherConfiguration configuration;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  public AbstractParkingPhase(
      InternalTransportOrderService orderService,
      ParkingPositionSupplier parkingPosSupplier,
      Router router,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      TransportOrderUtil transportOrderUtil,
      DefaultDispatcherConfiguration configuration) {
    this.router = requireNonNull(router, "router");
    this.orderService = requireNonNull(orderService, "orderService");
    this.parkingPosSupplier = requireNonNull(parkingPosSupplier, "parkingPosSupplier");
    this.assignmentCandidateSelectionFilter = requireNonNull(assignmentCandidateSelectionFilter,
                                                             "assignmentCandidateSelectionFilter");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    parkingPosSupplier.initialize();

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    parkingPosSupplier.terminate();

    initialized = false;
  }

  public TransportOrderService getOrderService() {
    return orderService;
  }

  public DefaultDispatcherConfiguration getConfiguration() {
    return configuration;
  }

  protected void createParkingOrder(Vehicle vehicle) {
    Point vehiclePosition = orderService.fetchObject(Point.class, vehicle.getCurrentPosition());

    // Get a suitable parking position for the vehicle.
    Optional<Point> parkPos = parkingPosSupplier.findParkingPosition(vehicle);
    LOG.debug("Parking position for {}: {}", vehicle, parkPos);
    // If we could not find a suitable parking position at all, just leave the vehicle where it is.
    if (!parkPos.isPresent()) {
      LOG.info("{}: Did not find a suitable parking position.", vehicle.getName());
      return;
    }
    // Create a destination for the point.
    List<DestinationCreationTO> parkDests = Arrays.asList(
        new DestinationCreationTO(parkPos.get().getName(), DriveOrder.Destination.OP_PARK)
    );
    // Create a transport order for parking and verify its processability.
    TransportOrder parkOrder = orderService.createTransportOrder(
        new TransportOrderCreationTO("Park-", parkDests)
            .withIncompleteName(true)
            .withDispensable(true)
            .withIntendedVehicleName(vehicle.getName())
    );
    Optional<AssignmentCandidate> candidate = computeCandidate(vehicle, vehiclePosition, parkOrder)
        .filter(c -> assignmentCandidateSelectionFilter.apply(c).isEmpty());
    // XXX Change this to Optional.ifPresentOrElse() once we're at Java 9+.
    if (candidate.isPresent()) {
      transportOrderUtil.assignTransportOrder(candidate.get().getVehicle(),
                                              candidate.get().getTransportOrder(),
                                              candidate.get().getDriveOrders());
    }
    else {
      // Mark the order as failed, since the vehicle cannot execute it.
      orderService.updateTransportOrderState(parkOrder.getReference(), TransportOrder.State.FAILED);
    }
  }

  private Optional<AssignmentCandidate> computeCandidate(Vehicle vehicle,
                                                         Point vehiclePosition,
                                                         TransportOrder order) {
    return router.getRoute(vehicle, vehiclePosition, order)
        .map(driveOrders -> new AssignmentCandidate(vehicle, order, driveOrders));
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/vehicle/VehicleComparatorByEnergyLevel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.vehicle;

import java.util.Comparator;
import org.opentcs.data.model.Vehicle;

/**
 * Compares {@link Vehicle}s by energy level, sorting higher energy levels up.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleComparatorByEnergyLevel
    implements Comparator<Vehicle> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "BY_ENERGY_LEVEL";

  /**
   * Compares two vehicles by their energy level.
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param vehicle1 The first vehicle.
   * @param vehicle2 The second vehicel.
   * @return the value 0 if vehicle1 and vehicle2 have the same energy level;
   * a value less than 0 if vehicle1 has a higher energy level than vehicle2;
   * and a value greater than 0 otherwise.
   */
  @Override
  public int compare(Vehicle vehicle1, Vehicle vehicle2) {
    return -Integer.compare(vehicle1.getEnergyLevel(), vehicle2.getEnergyLevel());
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/LabeledLocationFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import com.google.common.base.Strings;
import com.google.inject.assistedinject.Assisted;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventObject;
import java.util.LinkedList;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.Action;
import org.jhotdraw.draw.handle.Handle;
import org.opentcs.guing.components.drawing.ZoomPoint;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.model.elements.LocationModel;

/**
 * {@link LocationFigure} with a label.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class LabeledLocationFigure
    extends LabeledFigure {

  /**
   * The tool tip text generator.
   */
  private final ToolTipTextGenerator textGenerator;

  /**
   * Creates a new instance.
   *
   * @param figure The presentation figure.
   * @param textGenerator The tool tip text generator.
   */
  @Inject
  public LabeledLocationFigure(@Assisted LocationFigure figure,
                               ToolTipTextGenerator textGenerator) {
    requireNonNull(figure, "figure");
    this.textGenerator = requireNonNull(textGenerator, "textGenerator");

    setPresentationFigure(figure);
  }

  @Override
  public LocationFigure getPresentationFigure() {
    return (LocationFigure) super.getPresentationFigure();
  }

  @Override
  public Shape getShape() {
    return getPresentationFigure().getDrawingArea();
  }

  @Override
  public String getToolTipText(Point2D.Double p) {
    return textGenerator.getToolTipText(getPresentationFigure().getModel());
  }

  @Override
  public LabeledLocationFigure clone() {
    // Do NOT clone the label here.
    LabeledLocationFigure that = (LabeledLocationFigure) super.clone();

    if (that.getChildCount() > 0) {
      that.removeChild(0);
    }

    LocationFigure thatPresentationFigure = that.getPresentationFigure();
    thatPresentationFigure.addFigureListener(that.eventHandler);
    // Force loading of the symbol bitmap
    thatPresentationFigure.propertiesChanged(null);

    return that;
  }

  @Override
  public Collection<Action> getActions(Point2D.Double p) {
    LinkedList<Action> editOptions = new LinkedList<>();

    return editOptions;
  }

  @Override
  public Collection<Handle> createHandles(int detailLevel) {
    if (!isVisible()) {
      return new ArrayList<>();
    }

    return super.createHandles(detailLevel);
  }

  @Override
  public int getLayer() {
    return getPresentationFigure().getLayer();
  }

  @Override
  public boolean isVisible() {
    return getPresentationFigure().isVisible();
  }

  @Override
  public void propertiesChanged(AttributesChangeEvent event) {
    if (event.getInitiator().equals(this)) {
      return;
    }

    // Move the figure if the model coordinates have been changed in the
    // Properties panel
    Origin origin = get(FigureConstants.ORIGIN);

    if (origin != null) {
      LocationFigure lf = getPresentationFigure();

      if (lf.getModel().getPropertyLayoutPositionX().hasChanged()
          || lf.getModel().getPropertyLayoutPositionY().hasChanged()) {
        getLabel().willChange();
        Point2D exact
            = origin.calculatePixelPositionExactly(lf.getModel().getPropertyLayoutPositionX(),
                                                   lf.getModel().getPropertyLayoutPositionY());
        double scale = lf.getZoomPoint().scale();
        double xNew = exact.getX() / scale;
        double yNew = exact.getY() / scale;
        Point2D.Double anchor = new Point2D.Double(xNew, yNew);
        setBounds(anchor, anchor);
        getLabel().changed();
      }
    }

    // Update the image of the actual Location type
    getPresentationFigure().propertiesChanged(event);

    invalidate();
    // also update the label.
    fireFigureChanged();
  }

  @Override
  public void scaleModel(EventObject event) {
    Origin origin = get(FigureConstants.ORIGIN);

    if (origin != null) {
      LocationFigure lf = getPresentationFigure();

      Point2D exact
          = origin.calculatePixelPositionExactly(lf.getModel().getPropertyLayoutPositionX(),
                                                 lf.getModel().getPropertyLayoutPositionY());
      Point2D.Double anchor = new Point2D.Double(exact.getX(), exact.getY());
      setBounds(anchor, anchor);
    }

    invalidate();
    // also update the label.
    fireFigureChanged();
  }

  @Override
  public void updateModel() {
    Origin origin = get(FigureConstants.ORIGIN);
    LocationFigure lf = getPresentationFigure();
    LocationModel model = lf.getModel();
    CoordinateProperty cpx = model.getPropertyModelPositionX();
    CoordinateProperty cpy = model.getPropertyModelPositionY();
    if ((double) cpx.getValue() == 0.0 && (double) cpy.getValue() == 0.0) {
      origin.calculateRealPosition(lf.center(), cpx, cpy);
      cpx.markChanged();
      cpy.markChanged();
    }
    ZoomPoint zoomPoint = lf.getZoomPoint();
    if (zoomPoint != null && origin != null) {
      StringProperty lpx = model.getPropertyLayoutPositionX();
      int oldX = 0;

      if (!Strings.isNullOrEmpty(lpx.getText())) {
        oldX = (int) Double.parseDouble(lpx.getText());
      }
      int newX = (int) (zoomPoint.getX() * origin.getScaleX());

      if (newX != oldX) {
        lpx.setText(String.format("%d", newX));
        lpx.markChanged();
      }

      StringProperty lpy = model.getPropertyLayoutPositionY();

      int oldY = 0;
      if (!Strings.isNullOrEmpty(lpy.getText())) {
        oldY = (int) Double.parseDouble(lpy.getText());
      }

      int newY = (int) (-zoomPoint.getY() * origin.getScaleY());  // Vorzeichen!

      if (newY != oldY) {
        lpy.setText(String.format("%d", newY));
        lpy.markChanged();
      }

      // Offset of the labels of the location will be updated here.
      StringProperty propOffsetX = model.getPropertyLabelOffsetX();
      if (Strings.isNullOrEmpty(propOffsetX.getText())) {
        propOffsetX.setText(String.format("%d", TCSLabelFigure.DEFAULT_LABEL_OFFSET_X));
      }

      StringProperty propOffsetY = model.getPropertyLabelOffsetY();
      if (Strings.isNullOrEmpty(propOffsetY.getText())) {
        propOffsetY.setText(String.format("%d", TCSLabelFigure.DEFAULT_LABEL_OFFSET_Y));
      }

    }
    // update the type.
    model.getPropertyType().markChanged();

    model.propertiesChanged(this);
    // also update the label.
    fireFigureChanged();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/ModelComponentFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * A factory for ModelComponents.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelComponentFactory {


  /**
   * Creates a new instance.
   */
  public ModelComponentFactory() {
  }

  public LayoutModel createLayoutModel() {
    return new LayoutModel();
  }

  public VehicleModel createVehicleModel() {
    return new VehicleModel();
  }

  public LocationTypeModel createLocationTypeModel() {
    return new LocationTypeModel();
  }

  public BlockModel createBlockModel() {
    return new BlockModel();
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/LayerWrappersProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property that contains a list of layer wrappers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerWrappersProperty
    extends AbstractComplexProperty {

  /**
   * Creates a new instance.
   *
   * @param model The model component this property belongs to.
   * @param layerWrappers The layer wrappers.
   */
  public LayerWrappersProperty(ModelComponent model, Map<Integer, LayerWrapper> layerWrappers) {
    super(model);
    fValue = layerWrappers;
  }

  @Override
  public Object getComparableValue() {
    return this.toString();
  }

  @Override
  public String toString() {
    return getValue().values().stream()
        .sorted(Comparator.comparing(wrapper -> wrapper.getLayer().getId()))
        .map(wrapper -> wrapper.getLayer().getName())
        .collect(Collectors.joining(", "));
  }

  @Override
  public void copyFrom(Property property) {
    LayerWrappersProperty other = (LayerWrappersProperty) property;
    Map<Integer, LayerWrapper> items = new HashMap<>(other.getValue());
    setValue(items);
  }

  @Override
  @SuppressWarnings("unchecked")
  public Map<Integer, LayerWrapper> getValue() {
    return (Map) super.getValue();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/package-info.java<|end_filename|>
/**
 * Interfaces and classes for transparently providing an openTCS kernel's
 * functionality via RMI.
 */
package org.opentcs.access.rmi;


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/LocationTypeModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.ResourceBundle;
import org.opentcs.data.ObjectPropConstants;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.visualization.LocationRepresentation;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.LocationTypeActionsProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.components.properties.type.StringSetProperty;
import org.opentcs.guing.components.properties.type.SymbolProperty;
import org.opentcs.guing.model.AbstractModelComponent;

/**
 * Basic implementation of a location type.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class LocationTypeModel
    extends AbstractModelComponent {

  /**
   * The key for the possible actions on this type.
   */
  public static final String ALLOWED_OPERATIONS = "AllowedOperations";
  /**
   * The key fo the poissible peripheral actions on this type.
   */
  public static final String ALLOWED_PERIPHERAL_OPERATIONS = "AllowedPeripheralOperations";
  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * Reference to the LocationType object.
   */
  private LocationType locationType;

  /**
   * Creates a new instance.
   */
  public LocationTypeModel() {
    createProperties();
  }

  @Override
  public String getDescription() {
    return bundle.getString("locationTypeModel.description");
  }

  @Override
  public String getTreeViewName() {
    String treeViewName = getDescription() + " " + getName();

    return treeViewName;
  }

  public StringSetProperty getPropertyAllowedOperations() {
    return (StringSetProperty) getProperty(ALLOWED_OPERATIONS);
  }

  public StringSetProperty getPropertyAllowedPeripheralOperations() {
    return (StringSetProperty) getProperty(ALLOWED_PERIPHERAL_OPERATIONS);
  }

  public KeyValueSetProperty getPropertyMiscellaneous() {
    return (KeyValueSetProperty) getProperty(MISCELLANEOUS);
  }

  public SymbolProperty getPropertyDefaultRepresentation() {
    return (SymbolProperty) getProperty(ObjectPropConstants.LOCTYPE_DEFAULT_REPRESENTATION);
  }

  private void createProperties() {
    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("locationTypeModel.property_name.description"));
    pName.setHelptext(bundle.getString("locationTypeModel.property_name.helptext"));
    setProperty(NAME, pName);

    StringSetProperty pOperations = new LocationTypeActionsProperty(this);
    pOperations.setDescription(bundle.getString("locationTypeModel.property_allowedOperations.description"));
    pOperations.setHelptext(bundle.getString("locationTypeModel.property_allowedOperations.helptext"));
    setProperty(ALLOWED_OPERATIONS, pOperations);

    StringSetProperty pPeripheralOperations = new LocationTypeActionsProperty(this);
    pPeripheralOperations.setDescription(bundle.getString("locationTypeModel.property_allowedPeripheralOperations.description"));
    pPeripheralOperations.setHelptext(bundle.getString("locationTypeModel.property_allowedPeripheralOperations.helptext"));
    setProperty(ALLOWED_PERIPHERAL_OPERATIONS, pPeripheralOperations);

    SymbolProperty pSymbol = new SymbolProperty(this);
    pSymbol.setLocationRepresentation(LocationRepresentation.NONE);
    pSymbol.setDescription(bundle.getString("locationTypeModel.property_symbol.description"));
    pSymbol.setHelptext(bundle.getString("locationTypeModel.property_symbol.helptext"));
    setProperty(ObjectPropConstants.LOCTYPE_DEFAULT_REPRESENTATION, pSymbol);

    KeyValueSetProperty pMiscellaneous = new KeyValueSetProperty(this);
    pMiscellaneous.setDescription(bundle.getString("locationTypeModel.property_miscellaneous.description"));
    pMiscellaneous.setHelptext(bundle.getString("locationTypeModel.property_miscellaneous.helptext"));
    pMiscellaneous.setOperatingEditable(true);
    setProperty(MISCELLANEOUS, pMiscellaneous);
  }

  public LocationType getLocationType() {
    return locationType;
  }

  public void setLocationType(LocationType locationType) {
    this.locationType = locationType;
  }

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/KernelState.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import static java.util.Objects.requireNonNull;
import org.opentcs.access.Kernel.State;
import org.opentcs.components.Lifecycle;
import org.opentcs.kernel.persistence.ModelPersister;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.TCSObjectPool;

/**
 * The abstract base class for classes that implement state specific kernel
 * behaviour.
 *
 * @author <NAME> (Fraunhofer IML)
 */
abstract class KernelState
    implements Lifecycle {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The container of all course model and transport order objects.
   */
  private final TCSObjectPool globalObjectPool;
  /**
   * The model facade to the object pool.
   */
  private final Model model;
  /**
   * The persister loading and storing model data.
   */
  private final ModelPersister modelPersister;

  /**
   * Creates a new state.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param objectPool The object pool to be used.
   * @param model The model to be used.
   * @param modelPersister The model persister to be used.
   */
  KernelState(Object globalSyncObject,
              TCSObjectPool objectPool,
              Model model,
              ModelPersister modelPersister) {
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.globalObjectPool = requireNonNull(objectPool, "objectPool");
    this.model = requireNonNull(model, "model");
    this.modelPersister = requireNonNull(modelPersister, "modelPersister");
  }

  /**
   * Returns the current state.
   *
   * @return The current state.
   */
  public abstract State getState();

  protected Object getGlobalSyncObject() {
    return globalSyncObject;
  }

  protected ModelPersister getModelPersister() {
    return modelPersister;
  }

  protected TCSObjectPool getGlobalObjectPool() {
    return globalObjectPool;
  }

  protected Model getModel() {
    return model;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/management/PeripheralCommAdapterPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals.management;

import javax.swing.JPanel;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;

/**
 * A base class for panels associated with peripheral comm adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class PeripheralCommAdapterPanel
    extends JPanel {

  /**
   * Returns the title for this comm adapter panel.
   * The default implementation returns the accessible name from the panel's accessible context.
   *
   * @return The title for this comm adapter panel.
   */
  public String getTitle() {
    return getAccessibleContext().getAccessibleName();
  }

  /**
   * Notifies a comm adapter panel that the corresponding process model changed.
   * The comm adapter panel may want to update the content its representing.
   *
   * @param processModel The new process model.
   */
  public abstract void processModelChanged(PeripheralProcessModel processModel);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemotePeripheralJobService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * Declares the methods provided by the {@link PeripheralJobService} via RMI.
 *
 * <p>
 * The majority of the methods declared here have signatures analogous to their counterparts in
 * {@link PeripheralJobService}, with an additional {@link ClientID} parameter which serves the
 * purpose of identifying the calling client and determining its permissions.
 * </p>
 * <p>
 * To avoid redundancy, the semantics of methods that only pass through their arguments are not
 * explicitly documented here again. See the corresponding API documentation in
 * {@link PeripheralJobService} for these, instead.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RemotePeripheralJobService
    extends RemoteTCSObjectService,
            Remote {

  // CHECKSTYLE:OFF
  PeripheralJob createPeripheralJob(ClientID clientId, PeripheralJobCreationTO to)
      throws RemoteException;
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/PeripheralJobService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * Provides methods concerning {@link PeripheralJob}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralJobService
    extends TCSObjectService {

  /**
   * Creates a peripheral job.
   * A new peripheral job is created with a generated unique ID and all other attributes taken from
   * the given transfer object.
   * A copy of the newly created transport order is then returned.
   *
   * @param to Describes the peripheral job to be created.
   * @return A copy of the newly created peripheral job.
   * @throws ObjectUnknownException If any referenced object does not exist.
   * @throws ObjectExistsException If an object with the same name already exists in the model.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  PeripheralJob createPeripheralJob(PeripheralJobCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException;
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/extensions/controlcenter/vehicles/NullVehicleCommAdapterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.controlcenter.vehicles;

import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
import org.opentcs.drivers.vehicle.VehicleCommAdapterFactory;

/**
 * A Vehicle adapter factory that creates no vehicles adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullVehicleCommAdapterFactory
    implements VehicleCommAdapterFactory {

  /**
   * Creates a new instance.
   */
  public NullVehicleCommAdapterFactory() {
  }

  @Override
  public VehicleCommAdapterDescription getDescription() {
    return new NullVehicleCommAdapterDescription();
  }

  @Override
  public boolean providesAdapterFor(Vehicle vehicle) {
    return false;
  }

  @Override
  public VehicleCommAdapter getAdapterFor(Vehicle vehicle) {
    return null;
  }

  @Override
  public void initialize() {
  }

  @Override
  public boolean isInitialized() {
    return true;
  }

  @Override
  public void terminate() {
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/model/SystemModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.List;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.components.drawing.course.DrawingMethod;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.OtherGraphicalElement;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * Interface for the date model of the whole system model.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface SystemModel
    extends ModelComponent {

  /**
   * Returns this model's set of miscellaneous properties.
   *
   * @return This model's set of miscellaneous properties.
   */
  KeyValueSetProperty getPropertyMiscellaneous();

  /**
   * Add a main component to the system model.
   *
   * @param key The folder key
   * @param component The model component to be added to the folder
   */
  void addMainFolder(FolderKey key, ModelComponent component);

  /**
   * Return the main model component for the folder key.
   *
   * @param key The folder key
   * @return The model component that represents the main folder
   */
  ModelComponent getMainFolder(FolderKey key);

  /**
   * Returns the parent folder for a specified model component.
   *
   * @param item The model component where a parent folder should be found from
   * @return The parent folder of the item
   */
  ModelComponent getFolder(ModelComponent item);

  /**
   * Return all object of a specified class in a folder.
   *
   * @param foldername Key of the folder in which to search.
   * @param classType Tha class of the objects to find.
   * @return List of all object of specified type in the folder.
   */
  <T> List<T> getAll(FolderKey foldername, Class<T> classType);

  /**
   * Return all model components in the system model.
   *
   * @return List of all model components in the system model.
   */
  List<ModelComponent> getAll();

  /**
   * Notifies the model that all elements have been restored.
   */
  void onRestorationComplete();

  /**
   * Registers the given figure and associates it with the given model component.
   *
   * @param component The model component.
   * @param figure The figure to register.
   */
  void registerFigure(ModelComponent component, Figure figure);

  /**
   * Returns the figure for the given model component.
   *
   * @param component The model component.
   * @return The figure for the given model component.
   */
  Figure getFigure(ModelComponent component);

  /**
   * Return the drawing.
   *
   * @return The drawing.
   */
  Drawing getDrawing();

  /**
   * Return the drawing method.
   *
   * @return The drawing method
   */
  DrawingMethod getDrawingMethod();

  /**
   * Returns the component with the given name, if it exists.
   *
   * @param name The name.
   * @return The component with the given name, or {@code null}, if it does not exist.
   */
  ModelComponent getModelComponent(String name);

  /**
   * Return a list of all vehicles.
   *
   * @return The list of vehicle models
   */
  List<VehicleModel> getVehicleModels();

  /**
   * Return a vehicle with a specified name.
   *
   * @param name The name of the vehicle to search.
   * @return The vehicle or null if vehicle is not found.
   */
  VehicleModel getVehicleModel(String name);

  /**
   * Returns the layout model.
   *
   * @return The layout model.
   */
  LayoutModel getLayoutModel();

  /**
   * Return a list of all points.
   *
   * @return The list of points
   */
  List<PointModel> getPointModels();

  /**
   * Return a point with the specified name.
   *
   * @param name The name of the point to return.
   * @return The point or null if the name is not found.
   */
  PointModel getPointModel(String name);

  /**
   * Return all locations.
   *
   * @return List of all locations.
   */
  List<LocationModel> getLocationModels();

  /**
   * Return all locations with a specified location type.
   *
   * @param locationType The location type.
   * @return List of locations with the location type.
   */
  List<LocationModel> getLocationModels(LocationTypeModel locationType);

  /**
   * Return a location with the specified name.
   *
   * @param name The name of the location to return.
   * @return The location or null if the name is not found.
   */
  LocationModel getLocationModel(String name);

  /**
   * Return all paths.
   *
   * @return A list of all paths.
   */
  List<PathModel> getPathModels();

  /**
   * Return the PathModel with the given name.
   *
   * @param name Name of the path.
   * @return The PathModel.
   */
  PathModel getPathModel(String name);

  /**
   * Return all links in the model.
   *
   * @return A list of all links.
   */
  List<LinkModel> getLinkModels();

  /**
   * Return all links attached to a location with a specified location type.
   *
   * @param locationType The location type.
   * @return A list of all links attached to a location with a specified location type.
   */
  List<LinkModel> getLinkModels(LocationTypeModel locationType);

  /**
   * Return all location types.
   *
   * @return List of all location types.
   */
  List<LocationTypeModel> getLocationTypeModels();

  /**
   * Return the location type with the specified name.
   *
   * @param name The name of the location type to return.
   * @return The location type.
   */
  LocationTypeModel getLocationTypeModel(String name);

  /**
   * Returns the block model for the given name.
   *
   * @param name The block's name.
   * @return The block model.
   */
  BlockModel getBlockModel(String name);

  /**
   * Return all block models.
   *
   * @return A list of all block models.
   */
  List<BlockModel> getBlockModels();

  /**
   * Return all figures that are used for visualisation purposes.
   *
   * @return A list of all figures that are used for visualisation purposes.
   */
  List<OtherGraphicalElement> getOtherGraphicalElements();

  /**
   * Keys for the folders in a SystemModel.
   */
  public static enum FolderKey {

    VEHICLES,
    LAYOUT,
    POINTS,
    LOCATIONS,
    PATHS,
    LINKS,
    LOCATION_TYPES,
    BLOCKS,
    OTHER_GRAPHICAL_ELEMENTS
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/UniqueStringGenerator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.SortedSet;
import java.util.TreeSet;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * Provides a way to acquire unique strings.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <S> The type of the selectors/keys to be used for mapping to name
 * patterns.
 */
public class UniqueStringGenerator<S> {

  /**
   * Configured name patterns.
   */
  private final Map<S, NamePattern> namePatterns = new HashMap<>();
  /**
   * All strings known to this generator, sorted lexicographically.
   */
  private final SortedSet<String> existingStrings = new TreeSet<>();

  /**
   * Creates a new instance without any name patterns.
   */
  public UniqueStringGenerator() {
    // Do nada.
  }

  /**
   * Registers a name pattern for the given selector.
   *
   * @param selector The selector.
   * @param prefix The prefix of names to be used for the given selector.
   * @param suffixPattern The suffix pattern to be used for the given selector.
   */
  public void registerNamePattern(S selector,
                                  String prefix,
                                  String suffixPattern) {
    namePatterns.put(selector, new NamePattern(prefix, suffixPattern));
  }

  /**
   * Adds a String to those known by this generator. As a result, this generator
   * will never return a String that is equal to the given one.
   *
   * @param newString The string to be added.
   */
  public void addString(final String newString) {
    requireNonNull(newString, "newString is null");
    existingStrings.add(newString);
  }

  /**
   * Makes this generator forget a known String. As a result, this generator
   * might return a String that is equal to the given one in the future.
   *
   * @param rmString The string to be forgotten.
   */
  public void removeString(final String rmString) {
    requireNonNull(rmString, "rmString is null");
    existingStrings.remove(rmString);
  }

  /**
   * Returns true if this generator has this string.
   *
   * @param str The string to test.
   * @return true if this generator already has this string.
   */
  public boolean hasString(String str) {
    return existingStrings.contains(str);
  }

  /**
   * Removes all known Strings.
   */
  public void clear() {
    existingStrings.clear();
  }

  /**
   * Returns a string that is unique among all strings registered with this
   * generator.
   *
   * @param selector A selector for the name pattern to be used.
   * @return A string that is unique among all strings registered with this
   * generator.
   */
  public String getUniqueString(S selector) {
    requireNonNull(selector, "selector");

    NamePattern namePattern = namePatterns.get(selector);
    checkArgument(namePattern != null, "Unknown selector: %s", selector);

    return getUniqueString(namePattern.prefix, namePattern.suffixPattern);
  }

  /**
   * Returns a String that is unique among all known Strings in this generator.
   * The returned String will consist of the given prefix followed by an integer
   * formatted according to the given pattern. The pattern has to be of the form
   * understood by <code>java.text.DecimalFormat</code>.
   *
   * @param prefix The prefix of the String to be generated.
   * @param suffixPattern A pattern describing the suffix of the generated
   * String. Must be of the form understood by
   * <code>java.text.DecimalFormat</code>.
   * @return A String that is unique among all known Strings.
   */
  public String getUniqueString(final String prefix,
                                final String suffixPattern) {
    requireNonNull(suffixPattern, "suffixPattern is null");

    final String actualPrefix = prefix == null ? "" : prefix;
    final DecimalFormat format = new DecimalFormat(suffixPattern);
    final String lBound = actualPrefix + "0";
    final String uBound = actualPrefix + ":";
    final int prefixLength = actualPrefix.length();
    long maxSuffixValue = 0;
    // Get all existing strings with the same prefix and at least one digit
    // following it.
    for (String curName : existingStrings.subSet(lBound, uBound)) {
      // Check if the suffix contains only digits.
      boolean allDigits = containsOnlyDigits(curName.substring(prefixLength));
      // If the suffix contains only digits, parse it and remember the maximum
      // suffix value we found so far. (If the suffix contains other characters,
      // ignore this string - we generate suffixes with digits only, so there
      // can't be a collision.
      if (allDigits) {
        final long curSuffixValue = NumberParsers.parsePureDecimalLong(
            curName, prefixLength, curName.length() - prefixLength);
        maxSuffixValue
            = maxSuffixValue > curSuffixValue ? maxSuffixValue : curSuffixValue;
      }
    }
    // Increment the highest value found and use that as the suffix
    return actualPrefix + format.format(maxSuffixValue + 1);
  }

  /**
   * Checks if the given string contains only (decimal) digits.
   *
   * @param input The string to be checked.
   * @return <code>true</code> if, and only if, the given string contains only
   * (decimal) digits.
   */
  private boolean containsOnlyDigits(String input) {
    assert input != null;
    for (int i = 0; i < input.length(); i++) {
      int digit = input.charAt(i) - '0';
      if (digit < 0 || digit > 9) {
        return false;
      }
    }
    return true;
  }

  /**
   * A name pattern.
   */
  private static class NamePattern {

    /**
     * The prefix to be used.
     */
    private final String prefix;
    /**
     * The suffix pattern to be used.
     */
    private final String suffixPattern;

    /**
     * Creates a new instance.
     *
     * @param prefix The prefix to be used.
     * @param suffixPattern The suffix pattern to be used.
     */
    private NamePattern(String prefix, String suffixPattern) {
      this.prefix = requireNonNull(prefix, "prefix");
      this.suffixPattern = requireNonNull(suffixPattern, "suffixPattern");
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/ZoomPoint.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.io.Serializable;

/**
 * Represents an exact point that won't change when zooming the model.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class ZoomPoint
    implements Serializable {

  /**
   * The x position with a scale of 1.
   */
  protected double fX;
  /**
   * The y position with a scale of 1.
   */
  protected double fY;
  /**
   * The current scale.
   */
  protected double fScale;

  /**
   * Creates a new instance of ZoomPoint
   */
  public ZoomPoint() {
    this(0, 0);
  }

  /**
   * Creates a new instance.
   *
   * @param x The x position for this point.
   * @param y The y position for this point.
   */
  public ZoomPoint(double x, double y) {
    this(x, y, 1.0);
  }

  /**
   * Creates a new instance.
   *
   * @param x The x position for this point.
   * @param y The y position for this point.
   * @param scale The current scale.
   */
  public ZoomPoint(double x, double y, double scale) {
    fX = x / scale;
    fY = y / scale;
    fScale = scale;
  }

  /**
   * Returns the current scale.
   */
  public double scale() {
    return fScale;
  }

  /**
   * Sets the x position.
   *
   * @param x the x position.
   */
  public void setX(double x) {
    fX = x;
  }

  /**
   * Sets the y position.
   *
   * @param y the y position.
   */
  public void setY(double y) {
    fY = y;
  }

  /**
   * Returns the x position.
   *
   * @return the x position.
   */
  public double getX() {
    return fX;
  }

  /**
   * Returns the y position.
   *
   * @return the y position.
   */
  public double getY() {
    return fY;
  }

  /**
   * Returns a point with the position.
   *
   * @return a point with the position.
   */
  public Point getPixelLocation() {
    int x = (int) (getX() * scale());
    int y = (int) (getY() * scale());

    return new Point(x, y);
  }

  /**
   * Returns the exact position of the point in pixels with the current zoom level.
   *
   * @return the exact position.
   */
  public Point2D getPixelLocationExactly() {
    double x = getX() * scale();
    double y = getY() * scale();

    return new Point2D.Double(x, y);
  }

  /**
   * Event that the scale has changed.
   *
   * @param scale The new scale factor.
   */
  public void scaleChanged(double scale) {
    fScale = scale;
  }

  /**
   * Event that the point has been moved by the user.
   *
   * @param x The x-coordinate in Pixel.
   * @param y The y-coordinate in Pixel.
   */
  public void movedByMouse(int x, int y) {
    fX = x / scale();
    fY = y / scale();
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/PlantOverviewStarter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.app.Application;
import org.opentcs.guing.event.EventLogger;
import org.opentcs.guing.exchange.AttributeAdapterRegistry;
import org.opentcs.guing.exchange.KernelEventFetcher;
import org.opentcs.guing.exchange.OpenTCSEventDispatcher;
import org.opentcs.guing.peripherals.jobs.PeripheralJobsContainer;
import org.opentcs.guing.transport.orders.TransportOrdersContainer;
import org.opentcs.guing.transport.sequences.OrderSequencesContainer;

/**
 * The plant overview application's entry point.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PlantOverviewStarter {

  /**
   * Our startup progress indicator.
   */
  private final ProgressIndicator progressIndicator;
  /**
   * The enclosing application.
   */
  private final Application application;
  /**
   * The actual document view.
   */
  private final OpenTCSView opentcsView;
  /**
   *
   */
  private final EventLogger eventLogger;
  /**
   * Fetches events from the kernel, if connected, and publishes them via the local event bus.
   */
  private final KernelEventFetcher kernelEventFetcher;
  /**
   * Dispatches openTCS event from kernel objects to corresponding model components.
   */
  private final OpenTCSEventDispatcher eventDispatcher;

  private final AttributeAdapterRegistry attributeAdapterRegistry;
  /**
   * Maintains a set of all transport orders existing on the kernel side.
   */
  private final TransportOrdersContainer transportOrdersContainer;
  /**
   * Maintains a set of all peripheral jobs existing on the kernel side.
   */
  private final PeripheralJobsContainer peripheralJobsContainer;
  /**
   * Maintains a set of all order sequences existing on the kernel side.
   */
  private final OrderSequencesContainer orderSequencesContainer;

  /**
   * Creates a new instance.
   *
   * @param progressIndicator The progress indicator to be used.
   * @param application The application to be used.
   * @param opentcsView The view to be used.
   * @param eventLogger The event logger.
   * @param kernelEventFetcher Fetches events from the kernel, if connected, and publishes them via
   * the local event bus.
   * @param eventDispatcher Dispatches openTCS event from kernel objects to corresponding model
   * components.
   * @param attributeAdapterRegistry Handles registering of model attribute adapters.
   * @param transportOrdersContainer Maintains a set of all transport orders existing on the kernel
   * side.
   * @param peripheralJobsContainer Maintains a set of all peripheral jobs existing on the kernel
   * side.
   * @param orderSequencesContainer Maintains a set of all peripheral jobs existing on the kernel
   * side.
   */
  @Inject
  public PlantOverviewStarter(ProgressIndicator progressIndicator,
                              Application application,
                              OpenTCSView opentcsView,
                              EventLogger eventLogger,
                              KernelEventFetcher kernelEventFetcher,
                              OpenTCSEventDispatcher eventDispatcher,
                              AttributeAdapterRegistry attributeAdapterRegistry,
                              TransportOrdersContainer transportOrdersContainer,
                              PeripheralJobsContainer peripheralJobsContainer,
                              OrderSequencesContainer orderSequencesContainer) {
    this.progressIndicator = requireNonNull(progressIndicator, "progressIndicator");
    this.application = requireNonNull(application, "application");
    this.opentcsView = requireNonNull(opentcsView, "opentcsView");
    this.eventLogger = requireNonNull(eventLogger, "eventLogger");
    this.kernelEventFetcher = requireNonNull(kernelEventFetcher, "kernelEventFetcher");
    this.eventDispatcher = requireNonNull(eventDispatcher, "eventDispatcher");
    this.attributeAdapterRegistry = requireNonNull(attributeAdapterRegistry,
                                                   "attributeAdapterRegistry");
    this.transportOrdersContainer = requireNonNull(transportOrdersContainer,
                                                   "transportOrdersContainer");
    this.peripheralJobsContainer = requireNonNull(peripheralJobsContainer,
                                                  "peripheralJobsContainer");
    this.orderSequencesContainer = requireNonNull(orderSequencesContainer,
                                                  "orderSequencesContainer");
  }

  public void startPlantOverview() {
    eventLogger.initialize();
    kernelEventFetcher.initialize();
    eventDispatcher.initialize();
    attributeAdapterRegistry.initialize();
    transportOrdersContainer.initialize();
    peripheralJobsContainer.initialize();
    orderSequencesContainer.initialize();

    opentcsView.init();
    progressIndicator.initialize();
    progressIndicator.setProgress(StartupProgressStatus.START_PLANT_OVERVIEW);
    progressIndicator.setProgress(StartupProgressStatus.SHOW_PLANT_OVERVIEW);
    opentcsView.setApplication(application);
    // Start the view.
    application.show(opentcsView);
    progressIndicator.terminate();
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/tree/elements/VehicleUserObjectOperating.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JPopupMenu;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.application.menus.MenuFactory;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;

/**
 * A Vehicle in the tree view.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class VehicleUserObjectOperating
    extends VehicleUserObject {

  /**
   * A factory for popup menus.
   */
  private final MenuFactory menuFactory;

  /**
   * Creates a new instance.
   *
   * @param model The corresponding vehicle object.
   * @param guiManager The gui manager.
   * @param modelManager Provides the current system model.
   * @param menuFactory A factory for popup menus.
   */
  @Inject
  public VehicleUserObjectOperating(@Assisted VehicleModel model,
                                    GuiManager guiManager,
                                    ModelManager modelManager,
                                    MenuFactory menuFactory) {
    super(model, guiManager, modelManager);
    this.menuFactory = requireNonNull(menuFactory, "menuFactory");
  }

  @Override
  public JPopupMenu getPopupMenu() {
    return menuFactory.createVehiclePopupMenu(selectedVehicles);
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/gui/dialog/ConnectionParamSet.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.gui.dialog;

import java.rmi.registry.Registry;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkArgument;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * A set of parameters for a connection to the portal.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ConnectionParamSet {

  /**
   * The description.
   */
  private final String description;
  /**
   * The host name.
   */
  private final String host;
  /**
   * The port number.
   */
  private final int port;

  /**
   * Creates a new instance.
   *
   * @param description The description for this connection.
   * @param host The host to be used.
   * @param port The port number to be used.
   * @throws IllegalArgumentException If the port number is out of the range of valid port numbers.
   */
  public ConnectionParamSet(String description, String host, int port) {
    this.description = requireNonNull(description, "description");
    this.host = requireNonNull(host);
    this.port = checkInRange(port, 0, 65535, "port");
  }

  /**
   * Creates a new instance.
   *
   * @param description The description for this connection.
   * @param host The host to be used.
   * @param port The port number to be used.
   * @throws NumberFormatException If the port string does not contain a parseable port number.
   * @throws IllegalArgumentException If the port number is out of the range of valid port numbers.
   */
  public ConnectionParamSet(String description, String host, String port)
      throws NumberFormatException, IllegalArgumentException {
    this(description, host, Integer.parseInt(port));
  }

  /**
   * Creates a new instance with the description, host and port parsed from the given string, which
   * must follow a pattern of "description:host:port".
   *
   * @param paramString The string containing the description, host and port.
   */
  public ConnectionParamSet(String paramString) {
    requireNonNull(paramString, "paramString");
    String[] split = paramString.split("\\|", 3);
    checkArgument(split.length == 3,
                  "Could not parse input as 'description:host:port': %s",
                  paramString);
    this.description = split[0];
    this.host = split[1];
    this.port = checkInRange(Integer.parseInt(split[2]), 0, 65535, "port");
  }

  /**
   * Creates a new instance for host "localhost" and port 1099.
   */
  public ConnectionParamSet() {
    this("Localhost", "localhost", Registry.REGISTRY_PORT);
  }

  /**
   * Returns the description.
   * 
   * @return The description.
   */
  public String getDescription() {
    return description;
  }
  
  /**
   * Returns the host parameter.
   *
   * @return The host parameter.
   */
  public String getHost() {
    return host;
  }

  /**
   * Returns the port parameter.
   *
   * @return The port parameter.
   */
  public int getPort() {
    return port;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof ConnectionParamSet)) {
      return false;
    }
    ConnectionParamSet other = (ConnectionParamSet) o;
    return description.equals(other.description) && host.equals(other.host) && port == other.port;
  }

  @Override
  public int hashCode() {
    int hash = 7;
    hash = 23 * hash + Objects.hashCode(this.description);
    hash = 23 * hash + Objects.hashCode(this.host);
    hash = 23 * hash + this.port;
    return hash;
  }

  @Override
  public String toString() {
    return getDescription() + " - " + getHost() + ":" + getPort();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/PlantModelService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import java.util.Map;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;

/**
 * Provides methods concerning the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PlantModelService
    extends TCSObjectService {

  /**
   * Creates a new plant model with the objects described in the given transfer object.
   * Implicitly saves/persists the new plant model.
   *
   * @param to The transfer object describing the plant model objects to be created.
   * @throws ObjectUnknownException If any referenced object does not exist.
   * @throws ObjectExistsException If an object with the same name already exists in the model.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   * @throws IllegalStateException If there was a problem persisting the model.
   */
  void createPlantModel(PlantModelCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException,
             IllegalStateException;

  /**
   * Returns the name of the model that is currently loaded in the kernel.
   *
   * @return The name of the currently loaded model.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  String getModelName()
      throws KernelRuntimeException;

  /**
   * Returns the model's properties.
   *
   * @return The model's properties.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  Map<String, String> getModelProperties()
      throws KernelRuntimeException;

  /**
   * Updates a location's lock state.
   *
   * @param ref A reference to the location to be updated.
   * @param locked Indicates whether the location is to be locked ({@code true}) or unlocked
   * ({@code false}).
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void updateLocationLock(TCSObjectReference<Location> ref, boolean locked)
      throws ObjectUnknownException, KernelRuntimeException;
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/candidate/CandidateComparatorByVehicleName.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.candidate;

import java.util.Comparator;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorByName;

/**
 * Compares {@link AssignmentCandidate}s by name of the vehicle.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorByVehicleName
    implements Comparator<AssignmentCandidate> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "BY_VEHICLE_NAME";

  private final Comparator<Vehicle> delegate = new VehicleComparatorByName();

  @Override
  public int compare(AssignmentCandidate candidate1, AssignmentCandidate candidate2) {
    return delegate.compare(candidate1.getVehicle(), candidate2.getVehicle());
  }

}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/CandidateComparatorDeadlineAtRiskFirstTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.mockito.Mockito;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorDeadlineAtRiskFirst;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorDeadlineAtRiskFirst;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorDeadlineAtRiskFirstTest {

  private CandidateComparatorDeadlineAtRiskFirst comparator;

  @Before
  public void setUp() {
    DefaultDispatcherConfiguration configuration = Mockito.mock(DefaultDispatcherConfiguration.class);
    Mockito.when(configuration.deadlineAtRiskPeriod()).thenReturn(Long.valueOf(60 * 60 * 1000));

    this.comparator = new CandidateComparatorDeadlineAtRiskFirst(
        new TransportOrderComparatorDeadlineAtRiskFirst(configuration)
    );
  }

  @Test
  public void sortCriticalDeadlinesUp() {
    Instant deadline = Instant.now();
    AssignmentCandidate candidate1 = candidateWithDeadline(deadline.plus(270, ChronoUnit.MINUTES));
    AssignmentCandidate candidate2 = candidateWithDeadline(deadline.plus(30, ChronoUnit.MINUTES));
    AssignmentCandidate candidate3 = candidateWithDeadline(deadline.plus(180, ChronoUnit.MINUTES));

    List<AssignmentCandidate> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate2)));
  }

  private AssignmentCandidate candidateWithDeadline(Instant time) {
    TransportOrder deadlinedOrder
        = new TransportOrder("Some order", new ArrayList<>()).withDeadline(time);
    Route.Step dummyStep = new Route.Step(null,
                                          null,
                                          new Point("Point1"),
                                          Vehicle.Orientation.FORWARD,
                                          1);
    Route route = new Route(Arrays.asList(dummyStep), 10);
    List<DriveOrder> driveOrders = Arrays.asList(
        new DriveOrder(new DriveOrder.Destination(new Point("Point2").getReference()))
            .withRoute(route)
    );

    return new AssignmentCandidate(new Vehicle("Vehicle1"),
                                   deadlinedOrder,
                                   driveOrders);
  }

  private TransportOrderComparatorDeadlineAtRiskFirst createOrderComparator() {
    DefaultDispatcherConfiguration configuration = Mockito.mock(DefaultDispatcherConfiguration.class);
    Mockito.when(configuration.deadlineAtRiskPeriod()).thenReturn(Long.valueOf(10));
    return new TransportOrderComparatorDeadlineAtRiskFirst(configuration);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/CompositeVehicleCandidateComparatorTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.mockito.Mockito;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeVehicleCandidateComparator;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByInitialRoutingCosts;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeVehicleCandidateComparatorTest {

  private CompositeVehicleCandidateComparator comparator;
  private DefaultDispatcherConfiguration configuration;
  private Map<String, Comparator<AssignmentCandidate>> availableComparators;

  @Before
  public void setUp() {
    configuration = Mockito.mock(DefaultDispatcherConfiguration.class);
    availableComparators = new HashMap<>();
  }

  @Test
  public void sortNamesUpForOtherwiseEqualInstances() {

    Mockito.when(configuration.vehicleCandidatePriorities())
        .thenReturn(new LinkedList<>());
    comparator = new CompositeVehicleCandidateComparator(configuration, availableComparators);

    AssignmentCandidate candidate1 = candidateWithName("AA");
    AssignmentCandidate candidate2 = candidateWithName("CC");
    AssignmentCandidate candidate3 = candidateWithName("AB");

    List<AssignmentCandidate> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate1)));
    assertThat(list.get(1), is(theInstance(candidate3)));
    assertThat(list.get(2), is(theInstance(candidate2)));
  }

  @Test
  public void sortsByNameAndEnergylevel() {
    Mockito.when(configuration.vehicleCandidatePriorities())
        .thenReturn(new LinkedList<>());
    comparator = new CompositeVehicleCandidateComparator(configuration, availableComparators);

    AssignmentCandidate candidate1 = candidateWithNameEnergylevel("AA", 1);
    AssignmentCandidate candidate2 = candidateWithNameEnergylevel("CC", 2);
    AssignmentCandidate candidate3 = candidateWithNameEnergylevel("BB", 2);

    List<AssignmentCandidate> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate3)));
    assertThat(list.get(1), is(theInstance(candidate2)));
    assertThat(list.get(2), is(theInstance(candidate1)));
  }

  @Test
  public void sortsByNameAndRoutingCostAndEnergyLevel() {
    String initRoutingCostKey = "BY_INITIAL_ROUTING_COSTS";
    Mockito.when(configuration.vehicleCandidatePriorities())
        .thenReturn(Arrays.asList(initRoutingCostKey));
    availableComparators.put(initRoutingCostKey,
                             new CandidateComparatorByInitialRoutingCosts());

    comparator = new CompositeVehicleCandidateComparator(configuration, availableComparators);

    AssignmentCandidate candidate1 = candidateWithNameEnergylevelInitialRoutingCosts("AA", 3, 60);
    AssignmentCandidate candidate2 = candidateWithNameEnergylevelInitialRoutingCosts("CC", 2, 60);
    AssignmentCandidate candidate3 = candidateWithNameEnergylevelInitialRoutingCosts("BB", 1, 20);
    AssignmentCandidate candidate4 = candidateWithNameEnergylevelInitialRoutingCosts("DD", 1, 20);

    List<AssignmentCandidate> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);
    list.add(candidate4);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate3)));
    assertThat(list.get(1), is(theInstance(candidate4)));
    assertThat(list.get(2), is(theInstance(candidate1)));
    assertThat(list.get(3), is(theInstance(candidate2)));
  }

  private AssignmentCandidate candidateWithName(String name) {
    TransportOrder trasportOrder = new TransportOrder("TOrder-1", new ArrayList<>());
    return new AssignmentCandidate(new Vehicle(name),
                                   trasportOrder,
                                   buildDriveOrders(10));
  }

  private AssignmentCandidate candidateWithNameEnergylevel(String name,
                                                           int energyLevel) {
    TransportOrder trasportOrder = new TransportOrder("TOrder-1", new ArrayList<>());
    return new AssignmentCandidate(new Vehicle(name).withEnergyLevel(energyLevel),
                                   trasportOrder,
                                   buildDriveOrders(10));
  }

  private AssignmentCandidate candidateWithNameEnergylevelInitialRoutingCosts(String name,
                                                                              int energyLevel,
                                                                              long routingCost) {
    TransportOrder trasportOrder = new TransportOrder("TOrder-1", new ArrayList<>());
    return new AssignmentCandidate(new Vehicle(name).withEnergyLevel(energyLevel),
                                   trasportOrder,
                                   buildDriveOrders(routingCost));
  }

  private List<DriveOrder> buildDriveOrders(long routingCost) {
    Route.Step dummyStep
        = new Route.Step(null, null, new Point("Point1"), Vehicle.Orientation.FORWARD, 1);
    Route route = new Route(Arrays.asList(dummyStep), routingCost);
    List<DriveOrder> driveOrders = new LinkedList<>();
    driveOrders.add(new DriveOrder(new DriveOrder.Destination(new Point("Point2").getReference()))
        .withRoute(route));
    return driveOrders;
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteTransportOrderServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;

/**
 * The default implementation of the transport order service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemoteTransportOrderServiceProxy
    extends RemoteTCSObjectServiceProxy<RemoteTransportOrderService>
    implements TransportOrderService {

  @Override
  public OrderSequence createOrderSequence(OrderSequenceCreationTO to)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().createOrderSequence(getClientId(), to);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public TransportOrder createTransportOrder(TransportOrderCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().createTransportOrder(getClientId(), to);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void markOrderSequenceComplete(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().markOrderSequenceComplete(getClientId(), ref);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/application/toolbar/PaletteToolBarBorder.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.toolbar;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.MultipleGradientPaint;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JToolBar;

/**
 * A toolbar border.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PaletteToolBarBorder
    extends org.jhotdraw.gui.plaf.palette.PaletteToolBarBorder {

  private final static float[] ENABLED_STOPS = new float[] {0f, 0.5f, 1f};
  private final static Color[] ENABLED_STOP_COLORS = new Color[] {
    new Color(0xf8f8f8), new Color(0xc8c8c8), new Color(0xf8f8f8)
  };

  @Override
  public void paintBorder(Component component, Graphics gr, int x, int y, int w, int h) {
    Graphics2D g = (Graphics2D) gr;

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

    if ((component instanceof JToolBar) /* && ((((JToolBar) component).getUI()) instanceof PaletteToolBarUI) */) {
      JToolBar c = (JToolBar) component;

      if (c.isFloatable()) {
        int borderColor = 0x80ff0000;
        float[] stops = ENABLED_STOPS;
        Color[] stopColors = ENABLED_STOP_COLORS;

        g.setColor(new Color(borderColor, true));
        LinearGradientPaint lgp = new LinearGradientPaint(
            new Point2D.Float(1, 1), new Point2D.Float(19, 1),
            stops, stopColors,
            MultipleGradientPaint.CycleMethod.REPEAT);
        g.setPaint(lgp);
        g.fillRect(1, 1, 7 - 2, h - 2);
        ImageIcon icon = new ImageIcon(getClass().getResource("/org/opentcs/guing/res/symbols/toolbar/border.jpg"));

        if (c.getComponentCount() != 0 && !(c.getComponents()[0] instanceof JLabel)) {
          JLabel label = new JLabel(icon);
          label.setFocusable(false);
          c.add(label, 0);
          label.getParent().setBackground(label.getBackground());
          label.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
        }
      }
    }
  }

  @Override
  public Insets getBorderInsets(Component component, Insets insets) {
    Insets newInsets = (insets == null) ? new Insets(0, 0, 0, 0) : insets;

    JComponent c = (JComponent) component;

    if (c.getClientProperty(org.jhotdraw.gui.plaf.palette.PaletteToolBarUI.TOOLBAR_INSETS_OVERRIDE_PROPERTY) instanceof Insets) {
      Insets override = (Insets) c.getClientProperty(org.jhotdraw.gui.plaf.palette.PaletteToolBarUI.TOOLBAR_INSETS_OVERRIDE_PROPERTY);
      newInsets.top = override.top;
      newInsets.left = override.left;
      newInsets.bottom = override.bottom;
      newInsets.right = override.right;

      return newInsets;
    }

    newInsets.top = 1;
    newInsets.left = 1;
    newInsets.bottom = 0;
    newInsets.right = 0;

    return newInsets;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/factories/CustomSslRMIClientSocketFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.factories;

import java.io.IOException;
import java.io.Serializable;
import java.net.Socket;
import java.rmi.server.RMIClientSocketFactory;
import static java.util.Objects.requireNonNull;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.rmi.ssl.SslRMIClientSocketFactory;

/**
 * This implementation is similar to {@link SslRMIClientSocketFactory} but allows the use of a
 * custom SSLConext.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class CustomSslRMIClientSocketFactory
    implements RMIClientSocketFactory,
               Serializable {

  /**
   * Provides an instance of {@link SSLContext} used to get the actual socket factory.
   */
  private final SecureSslContextFactory secureSslContextFactory;

  /**
   * Creates a new instance.
   *
   * @param secureSslContextFactory Provides an instance of {@link SSLContext} used to get the
   * actual socket factory.
   */
  public CustomSslRMIClientSocketFactory(SecureSslContextFactory secureSslContextFactory) {
    this.secureSslContextFactory = requireNonNull(secureSslContextFactory,
                                                  "secureSslContextFactory");
  }

  @Override
  public Socket createSocket(String host, int port)
      throws IOException {
    SSLContext context = secureSslContextFactory.createClientContext();
    SSLSocketFactory sf = context.getSocketFactory();
    SSLSocket socket = (SSLSocket) sf.createSocket(host, port);
    SSLParameters param = context.getSupportedSSLParameters();
    socket.setEnabledCipherSuites(param.getCipherSuites());
    socket.setEnabledProtocols(param.getProtocols());
    return socket;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/VehicleCommAdapterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Vehicle;

/**
 * Provides communication adapter instances for vehicles to be controlled.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleCommAdapterFactory
    extends Lifecycle {

  /**
   * Returns a {@link VehicleCommAdapterDescription} for the factory/the adapters provided.
   *
   * @return A {@link VehicleCommAdapterDescription} for the factory/the adapters provided.
   */
  VehicleCommAdapterDescription getDescription();

  /**
   * Checks whether this factory can provide a communication adapter for the
   * given vehicle.
   *
   * @param vehicle The vehicle to check for.
   * @return <code>true</code> if, and only if, this factory can provide a
   * communication adapter to control the given vehicle.
   */
  boolean providesAdapterFor(@Nonnull Vehicle vehicle);

  /**
   * Returns a communication adapter for controlling the given vehicle.
   *
   * @param vehicle The vehicle to be controlled.
   * @return A communication adapter for controlling the given vehicle, or
   * <code>null</code>, if this factory cannot provide an adapter for it.
   */
  @Nullable
  VehicleCommAdapter getAdapterFor(@Nonnull Vehicle vehicle);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/PlantOverviewStarter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.app.Application;
import org.opentcs.guing.event.EventLogger;

/**
 * The plant overview application's entry point.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PlantOverviewStarter {

  /**
   * Our startup progress indicator.
   */
  private final ProgressIndicator progressIndicator;
  /**
   * The enclosing application.
   */
  private final Application application;
  /**
   * The actual document view.
   */
  private final OpenTCSView opentcsView;
  /**
   * Provides logging for events published on the application event bus.
   */
  private final EventLogger eventLogger;

  /**
   * Creates a new instance.
   *
   * @param progressIndicator The progress indicator to be used.
   * @param application The application to be used.
   * @param opentcsView The view to be used.
   * @param eventLogger Provides logging for events published on the application event bus.
   */
  @Inject
  public PlantOverviewStarter(ProgressIndicator progressIndicator,
                              Application application,
                              OpenTCSView opentcsView,
                              EventLogger eventLogger) {
    this.progressIndicator = requireNonNull(progressIndicator, "progressIndicator");
    this.application = requireNonNull(application, "application");
    this.opentcsView = requireNonNull(opentcsView, "opentcsView");
    this.eventLogger = requireNonNull(eventLogger, "eventLogger");
  }

  public void startPlantOverview() {
    eventLogger.initialize();

    opentcsView.init();
    progressIndicator.initialize();
    progressIndicator.setProgress(StartupProgressStatus.START_PLANT_OVERVIEW);
    progressIndicator.setProgress(StartupProgressStatus.SHOW_PLANT_OVERVIEW);
    opentcsView.setApplication(application);
    // Start the view.
    application.show(opentcsView);
    progressIndicator.terminate();
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/VirtualVehicleConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure to {@link LoopbackCommunicationAdapter}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(VirtualVehicleConfiguration.PREFIX)
public interface VirtualVehicleConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "virtualvehicle";

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to enable to register/enable the loopback driver.",
      orderKey = "0_enable")
  boolean enable();

  @ConfigurationEntry(
      type = "Integer",
      description = "The adapter's command queue capacity.",
      orderKey = "1_attributes_1")
  int commandQueueCapacity();

  @ConfigurationEntry(
      type = "String",
      description = "The string to be treated as a recharge operation.",
      orderKey = "1_attributes_2")
  String rechargeOperation();

  @ConfigurationEntry(
      type = "Double",
      description = {"The simulation time factor.",
                     "1.0 is real time, greater values speed up simulation."},
      orderKey = "1_behaviour_3")
  double simulationTimeFactor();
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/DefaultPlantOverviewInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing;

import com.google.inject.TypeLiteral;
import java.io.File;
import java.util.List;
import java.util.Locale;
import javax.inject.Singleton;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.SslParameterSet;
import org.opentcs.access.rmi.KernelServicePortalBuilder;
import org.opentcs.access.rmi.factories.NullSocketFactoryProvider;
import org.opentcs.access.rmi.factories.SecureSocketFactoryProvider;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.common.GuestUserCredentials;
import org.opentcs.components.plantoverview.LocationTheme;
import org.opentcs.components.plantoverview.VehicleTheme;
import org.opentcs.customizations.ApplicationHome;
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.opentcs.drivers.LowLevelCommunicationEvent;
import org.opentcs.guing.application.ApplicationInjectionModule;
import org.opentcs.guing.components.ComponentsInjectionModule;
import org.opentcs.guing.exchange.ExchangeInjectionModule;
import org.opentcs.guing.exchange.SslConfiguration;
import org.opentcs.guing.model.ModelInjectionModule;
import org.opentcs.guing.peripherals.jobs.PeripheralJobInjectionModule;
import org.opentcs.guing.persistence.DefaultPersistenceInjectionModule;
import org.opentcs.guing.transport.TransportInjectionModule;
import org.opentcs.guing.util.PlantOverviewApplicationConfiguration;
import org.opentcs.guing.util.PlantOverviewOperatingApplicationConfiguration;
import org.opentcs.guing.util.UtilInjectionModule;
import org.opentcs.util.ClassMatcher;
import org.opentcs.util.gui.dialog.ConnectionParamSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Guice module for the openTCS plant overview application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPlantOverviewInjectionModule
    extends PlantOverviewInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG
      = LoggerFactory.getLogger(DefaultPlantOverviewInjectionModule.class);

  @Override
  protected void configure() {
    File applicationHome = new File(System.getProperty("opentcs.home", "."));
    bind(File.class)
        .annotatedWith(ApplicationHome.class)
        .toInstance(applicationHome);

    configurePlantOverviewDependencies();
    install(new ApplicationInjectionModule());
    install(new ComponentsInjectionModule());
    install(new ExchangeInjectionModule());
    install(new ModelInjectionModule());
    install(new DefaultPersistenceInjectionModule());
    install(new TransportInjectionModule());
    install(new PeripheralJobInjectionModule());
    install(new UtilInjectionModule());

    // Ensure there is at least an empty binder for pluggable panels.
    pluggablePanelFactoryBinder();
    // Ensure there is at least an empty binder for history entry formatters.
    objectHistoryEntryFormatterBinder();
  }

  private void configurePlantOverviewDependencies() {
    PlantOverviewApplicationConfiguration baseConfiguration
        = getConfigBindingProvider().get(PlantOverviewApplicationConfiguration.PREFIX,
                                         PlantOverviewApplicationConfiguration.class);
    PlantOverviewOperatingApplicationConfiguration configuration
        = getConfigBindingProvider().get(PlantOverviewApplicationConfiguration.PREFIX,
                                         PlantOverviewOperatingApplicationConfiguration.class);
    bind(PlantOverviewApplicationConfiguration.class)
        .toInstance(baseConfiguration);
    bind(PlantOverviewOperatingApplicationConfiguration.class)
        .toInstance(configuration);
    configurePlantOverview(configuration);
    configureThemes(configuration);
    configureSocketConnections();

    bind(new TypeLiteral<List<ConnectionParamSet>>() {
    })
        .toInstance(baseConfiguration.connectionBookmarks());
  }

  private void configureSocketConnections() {
    SslConfiguration sslConfiguration = getConfigBindingProvider().get(SslConfiguration.PREFIX,
                                                                       SslConfiguration.class);

    //Create the data object for the ssl configuration
    SslParameterSet sslParamSet = new SslParameterSet(SslParameterSet.DEFAULT_KEYSTORE_TYPE,
                                                      null,
                                                      null,
                                                      new File(sslConfiguration.truststoreFile()),
                                                      sslConfiguration.truststorePassword());
    bind(SslParameterSet.class).toInstance(sslParamSet);

    SocketFactoryProvider socketFactoryProvider;
    if (sslConfiguration.enable()) {
      socketFactoryProvider = new SecureSocketFactoryProvider(sslParamSet);
    }
    else {
      LOG.warn("SSL encryption disabled, connections will not be secured!");
      socketFactoryProvider = new NullSocketFactoryProvider();
    }

    //Bind socket provider to the kernel portal
    bind(KernelServicePortal.class)
        .toInstance(new KernelServicePortalBuilder(GuestUserCredentials.USER,
                                                   GuestUserCredentials.PASSWORD)
            .setSocketFactoryProvider(socketFactoryProvider)
            .setEventFilter(new ClassMatcher(LowLevelCommunicationEvent.class).negate())
            .build());
  }

  private void configureThemes(PlantOverviewOperatingApplicationConfiguration configuration) {
    bind(LocationTheme.class)
        .to(configuration.locationThemeClass())
        .in(Singleton.class);
    bind(VehicleTheme.class)
        .to(configuration.vehicleThemeClass())
        .in(Singleton.class);
  }

  private void configurePlantOverview(PlantOverviewOperatingApplicationConfiguration configuration) {
    Locale.setDefault(Locale.forLanguageTag(configuration.locale()));

    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException
               | UnsupportedLookAndFeelException ex) {
      LOG.warn("Could not set look-and-feel", ex);
    }
    // Show tooltips for 30 seconds (Default: 4 sec)
    ToolTipManager.sharedInstance().setDismissDelay(30 * 1000);
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/KeyValueSetProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.opentcs.guing.model.ModelComponent;

/**
 * An attribute which contains a quantity of key-value pairs.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class KeyValueSetProperty
    extends AbstractComplexProperty {

  /**
   * The quantity of key-value-pairs.
   */
  private List<KeyValueProperty> fItems = new ArrayList<>();

  /**
   * Creates a new instance.
   *
   * @param model The model component this property belongs to.
   */
  public KeyValueSetProperty(ModelComponent model) {
    super(model);
  }

  @Override
  public Object getComparableValue() {
    StringBuilder sb = new StringBuilder();

    for (KeyValueProperty property : fItems) {
      sb.append(property.getKey()).append(property.getValue());
    }

    return sb.toString();
  }

  /**
   * Adds a property.
   *
   * @param item The property to add.
   */
  public void addItem(KeyValueProperty item) {
    for (KeyValueProperty property : fItems) {
      if (item.getKey().equals(property.getKey())) {
        property.setKeyAndValue(property.getKey(), item.getValue());
        return;
      }
    }

    fItems.add(item);
  }

  /**
   * Removes a property.
   *
   * @param item The property to remove.
   */
  public void removeItem(KeyValueProperty item) {
    fItems.remove(item);
  }

  /**
   * Sets the list with key-value-pairs..
   *
   * @param items The values.
   */
  public void setItems(List<KeyValueProperty> items) {
    fItems = items;
  }

  /**
   * Returns all key-value-pairs.
   *
   * @return The properties.
   */
  public List<KeyValueProperty> getItems() {
    return fItems;
  }

  @Override
  public void copyFrom(Property property) {
    KeyValueSetProperty other = (KeyValueSetProperty) property;
    List<KeyValueProperty> items = new ArrayList<>(other.getItems());
    setItems(items);
  }

  @Override
  public String toString() {
    if (fValue != null) {
      return fValue.toString();
    }

    StringBuilder sb = new StringBuilder();
    Iterator<KeyValueProperty> iItems = getItems().iterator();

    while (iItems.hasNext()) {
      sb.append(iItems.next());

      if (iItems.hasNext()) {
        sb.append(", ");
      }
    }

    return sb.toString();
  }

  @Override
  public Object clone() {
    KeyValueSetProperty clone = (KeyValueSetProperty) super.clone();
    List<KeyValueProperty> items = new ArrayList<>(getItems());
    clone.setItems(items);

    return clone;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/package-info.java<|end_filename|>
/**
 * Interfaces for pluggable panels, themes and other components for a plant overview application.
 */
package org.opentcs.components.plantoverview;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemotePlantModelService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Map;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;

/**
 * Declares the methods provided by the {@link PlantModelService} via RMI.
 *
 * <p>
 * The majority of the methods declared here have signatures analogous to their counterparts in
 * {@link PlantModelService}, with an additional {@link ClientID} parameter which serves the purpose
 * of identifying the calling client and determining its permissions.
 * </p>
 * <p>
 * To avoid redundancy, the semantics of methods that only pass through their arguments are not
 * explicitly documented here again. See the corresponding API documentation in
 * {@link PlantModelService} for these, instead.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RemotePlantModelService
    extends RemoteTCSObjectService,
            Remote {

  // CHECKSTYLE:OFF
  void createPlantModel(ClientID clientId, PlantModelCreationTO to)
      throws RemoteException;

  String getModelName(ClientID clientId)
      throws RemoteException;

  Map<String, String> getModelProperties(ClientID clientId)
      throws RemoteException;

  void updateLocationLock(ClientID clientId, TCSObjectReference<Location> ref, boolean locked)
      throws RemoteException;
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/AbstractUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import static java.util.Objects.requireNonNull;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.persistence.ModelManager;

/**
 * Abstract implementation of a UserObject.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class AbstractUserObject
    implements UserObject {

  /**
   * The model component this user object represents.
   */
  private final ModelComponent fModelComponent;
  /**
   * The gui manager.
   */
  private final GuiManager guiManager;
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The parent object.
   */
  private ModelComponent parent;

  /**
   * Creates a new instance.
   *
   * @param modelComponent The corresponding model component.
   * @param guiManager The gui manager.
   * @param modelManager Provides access to the currently loaded system model.
   */
  public AbstractUserObject(ModelComponent modelComponent,
                            GuiManager guiManager,
                            ModelManager modelManager) {
    this.fModelComponent = requireNonNull(modelComponent, "modelComponent");
    this.guiManager = requireNonNull(guiManager, "guiManager");
    this.modelManager = requireNonNull(modelManager, "modelManager");
  }

  @Override // Object
  public String toString() {
    return fModelComponent.getTreeViewName();
  }

  @Override // UserObject
  public ModelComponent getModelComponent() {
    return fModelComponent;
  }

  @Override // UserObject
  public void selected() {
    getGuiManager().selectModelComponent(getModelComponent());
  }

  @Override // UserObject
  public boolean removed() {
    return getGuiManager().treeComponentRemoved(fModelComponent);
  }

  @Override // UserObject
  public void rightClicked(JComponent component, int x, int y) {
    JPopupMenu popupMenu = getPopupMenu();
    if (popupMenu != null) {
      popupMenu.show(component, x, y);
    }
  }

  @Override // UserObject
  public void doubleClicked() {
  }

  @Override // UserObject
  public JPopupMenu getPopupMenu() {
    return new JPopupMenu();
  }

  @Override // UserObject
  public ImageIcon getIcon() {
    return null;
  }

  /**
   * Is called when multiple objects in a tree are selected.
   */
  public void selectMultipleObjects() {
    getGuiManager().addSelectedModelComponent(getModelComponent());
  }

  @Override
  public ModelComponent getParent() {
    return parent;
  }

  @Override
  public void setParent(ModelComponent parent) {
    this.parent = parent;
  }

  protected GuiManager getGuiManager() {
    return guiManager;
  }

  protected ModelManager getModelManager() {
    return modelManager;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/QueryService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.components.kernel.Query;

/**
 * Provides generic/pluggable query functionality.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface QueryService {

  /**
   * Executes a query with the kernel and delivers the result.
   *
   * @param <T> The query/result type.
   * @param query The query/parameter object.
   * @return The query result.
   */
  <T> T query(Query<T> query);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayersPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.guing.util.IconToolkit;
import org.opentcs.util.gui.StringListCellRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A panel to display and edit layers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayersPanel
    extends JPanel {

  private static final Logger LOG = LoggerFactory.getLogger(LayersPanel.class);
  /**
   * The path containing the icons.
   */
  private static final String ICON_PATH = "/org/opentcs/guing/res/symbols/layer/";
  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewModeling.LAYERS_PATH);
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer manager.
   */
  private final LayerManager layerManager;
  /**
   * The layer group manager.
   */
  private final LayerGroupManager layerGroupManager;
  /**
   * The layer editor.
   */
  private final LayerEditorModeling layerEditor;
  /**
   * Provides the currently active layer.
   */
  private final ActiveLayerProvider activeLayerProvider;
  /**
   * The table to display available layers.
   */
  private JTable table;
  /**
   * The table model.
   */
  private LayersTableModel tableModel;

  @Inject
  public LayersPanel(ModelManager modelManager,
                     LayerManager layerManager,
                     LayerGroupManager layerGroupManager,
                     LayerEditorModeling layerEditor,
                     ActiveLayerProvider activeLayerProvider) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerManager = requireNonNull(layerManager, "layerManager");
    this.layerGroupManager = requireNonNull(layerGroupManager, "layerGroupManager");
    this.layerEditor = requireNonNull(layerEditor, "layerEditor");
    this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");

    initComponents();
  }

  private void initComponents() {
    setLayout(new BorderLayout());

    tableModel = new LayersTableModel(modelManager, activeLayerProvider, layerEditor);
    layerManager.setLayerChangeListener(tableModel);
    layerGroupManager.addLayerGroupChangeListener(tableModel);
    table = new JTable(tableModel);
    initTable();
    
    add(createToolBar(), BorderLayout.NORTH);
    add(new JScrollPane(table), BorderLayout.CENTER);
  }

  private void initTable() {
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    TableRowSorter<LayersTableModel> sorter = new TableRowSorter<>(tableModel);
    // Sort the table by the layer ordinals...
    sorter.setSortKeys(Arrays.asList(
        new RowSorter.SortKey(LayersTableModel.COLUMN_ORDINAL, SortOrder.DESCENDING)
    ));
    // ...but prevent manual sorting.
    for (int i = 0; i < table.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    table.setRowSorter(sorter);

    // Hide the column that shows the layer ordinals.
    table.removeColumn(table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_ORDINAL)));

    table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_GROUP_VISIBLE))
        .setCellRenderer(new DisabledCheckBoxCellRenderer());

    initActiveColumn();
    initGroupColumn();
  }

  private JToolBar createToolBar() {
    JToolBar toolBar = new JToolBar();
    toolBar.setFloatable(false);

    toolBar.add(createAddLayerButton());
    toolBar.add(createRemoveLayerButton());
    toolBar.add(createMoveLayerUpButton());
    toolBar.add(createMoveLayerDownButton());

    return toolBar;
  }

  private void initActiveColumn() {
    // Since our concept of layers allows only one active layer at a time, a representation of that
    // state as radio buttons seems to have the potential to be more intuitive for users.
    // Radio buttons usually come with/in a button group which ensures that only one of the radio
    // buttons in that group can be selected at a time. In a table, though, such a button group
    // doesn't seem to work very well if it's used to group radio buttons across multiple rows.
    // For that reason the behavior of radio buttons in a button group is "emulated" in/trough
    // the LayerManager implementation.
    TableColumn columnActive = table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_ACTIVE));
    columnActive.setCellEditor(new RadioButtonCellEditor());
    columnActive.setCellRenderer(new RadioButtonCellRenderer());
  }

  private void initGroupColumn() {
    TableColumn columnGroup = table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_GROUP));
    columnGroup.setCellRenderer(new LayerGroupCellRenderer());
    columnGroup.setCellEditor(new GroupCellEditor());
  }

  private JButton createAddLayerButton() {
    IconToolkit iconkit = IconToolkit.instance();
    JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "create-layer.16.png"));
    button.addActionListener(actionEvent -> {
      layerEditor.createLayer();
      table.getSelectionModel().setSelectionInterval(0, 0);
    });
    button.setToolTipText(BUNDLE.getString("layersPanel.button_addLayer.tooltipText"));

    return button;
  }

  private JButton createRemoveLayerButton() {
    IconToolkit iconkit = IconToolkit.instance();
    JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "delete-layer.16.png"));
    button.addActionListener(new RemoveLayerListener());
    button.setToolTipText(BUNDLE.getString("layersPanel.button_removeLayer.tooltipText"));

    // Allow the remove layer button to be pressed only if there's a layer selected and if there's
    // more than one layer in the model.
    table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
      button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
    });
    tableModel.addTableModelListener(tableModelEvent -> {
      button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
    });

    return button;
  }

  private JButton createMoveLayerUpButton() {
    IconToolkit iconkit = IconToolkit.instance();
    JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "move-layer-up.16.png"));
    button.setEnabled(false);
    button.addActionListener(actionEvent -> {
      int selectedRow = table.getSelectedRow();
      int selectedLayerId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();
      layerEditor.moveLayerUp(selectedLayerId);
    });
    button.setToolTipText(BUNDLE.getString("layersPanel.button_moveLayerUp.tooltipText"));

    // Allow the button to be pressed only if there's a layer selected.
    table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
      button.setEnabled(table.getSelectedRow() != -1);
    });

    return button;
  }

  private JButton createMoveLayerDownButton() {
    IconToolkit iconkit = IconToolkit.instance();
    JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "move-layer-down.16.png"));
    button.setEnabled(false);
    button.addActionListener(actionEvent -> {
      int selectedRow = table.getSelectedRow();
      int selectedLayerId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();
      layerEditor.moveLayerDown(selectedLayerId);
    });
    button.setToolTipText(BUNDLE.getString("layersPanel.button_moveLayerDown.tooltipText"));

    // Allow the button to be pressed only if there's a layer selected.
    table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
      button.setEnabled(table.getSelectedRow() != -1);
    });

    return button;
  }

  private class RemoveLayerListener
      implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
      int selectedRow = table.getSelectedRow();
      int selectedLayerId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();

      if (layerManager.containsComponents(selectedLayerId)) {
        int selectedOption = JOptionPane.showConfirmDialog(
            LayersPanel.this,
            BUNDLE.getString("layersPanel.optionPane_confirmLayerWithComponentsRemoval.message"),
            BUNDLE.getString("layersPanel.optionPane_confirmLayerWithComponentsRemoval.title"),
            JOptionPane.YES_NO_OPTION,
            JOptionPane.WARNING_MESSAGE
        );
        if (selectedOption == JOptionPane.NO_OPTION) {
          return;
        }
      }

      layerEditor.deleteLayer(selectedLayerId);
    }
  }

  private class RadioButtonCellRenderer
      implements TableCellRenderer {

    private final Border unfocusedCellBorder = BorderFactory.createEmptyBorder();
    private final Border focusedCellBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
    private final JRadioButton radioButton;

    public RadioButtonCellRenderer() {
      radioButton = new JRadioButton();
      radioButton.setHorizontalAlignment(JRadioButton.CENTER);
      radioButton.setBorderPainted(true);
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                   boolean hasFocus, int row, int col) {
      radioButton.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
      radioButton.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
      radioButton.setBorder(hasFocus ? focusedCellBorder : unfocusedCellBorder);
      radioButton.setSelected(Boolean.TRUE.equals(value));

      return radioButton;
    }
  }

  private class RadioButtonCellEditor
      extends AbstractCellEditor
      implements TableCellEditor {

    private final JRadioButton radioButton;

    public RadioButtonCellEditor() {
      radioButton = new JRadioButton();
      radioButton.setHorizontalAlignment(JRadioButton.CENTER);
      radioButton.addActionListener(actionEvent -> stopCellEditing());
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
                                                 boolean isSelected, int row, int col) {
      radioButton.setSelected(Boolean.TRUE.equals(value));
      return radioButton;
    }

    @Override
    public Object getCellEditorValue() {
      return radioButton.isSelected();
    }
  }

  private class GroupCellEditor
      extends DefaultCellEditor {

    private final DefaultComboBoxModel<LayerGroup> model;

    public GroupCellEditor() {
      super(new JComboBox<LayerGroup>());
      @SuppressWarnings("unchecked")
      JComboBox<LayerGroup> combobox = (JComboBox<LayerGroup>) getComponent();
      combobox.setRenderer(new StringListCellRenderer<>(group -> group.getName()));
      this.model = (DefaultComboBoxModel<LayerGroup>) combobox.getModel();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
                                                 boolean isSelected, int row, int column) {
      model.removeAllElements();
      List<LayerGroup> groups = modelManager.getModel().getLayoutModel().getPropertyLayerGroups()
          .getValue().values().stream()
          .sorted((o1, o2) -> Integer.compare(o1.getId(), o2.getId()))
          .collect(Collectors.toList());
      model.addAll(groups);
      model.setSelectedItem(table.getModel().getValueAt(row, column));

      return super.getTableCellEditorComponent(table, value, isSelected, row, column);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/edit/UndoRedoManager.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.action.edit;

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.inject.Inject;
import javax.swing.AbstractAction;
import javax.swing.Action;
import static javax.swing.Action.ACCELERATOR_KEY;
import static javax.swing.Action.LARGE_ICON_KEY;
import static javax.swing.Action.SMALL_ICON;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import static org.opentcs.guing.event.SystemModelTransitionEvent.Stage.UNLOADING;
import org.opentcs.guing.util.I18nPlantOverview;
import static org.opentcs.guing.util.I18nPlantOverview.MENU_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Same as javax.swing.UndoManager but provides actions for undo and redo
 * operations.
 *
 * @author <NAME>
 * @author <NAME> (Fraunhofer IML)
 */
public class UndoRedoManager
    extends UndoManager
    implements EventHandler {

  public static final String UNDO_ACTION_ID = "edit.undo";
  public static final String REDO_ACTION_ID = "edit.redo";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);

  /**
   * Sending this UndoableEdit event to the UndoRedoManager
   * disables the Undo and Redo functions of the manager.
   */
  public final static UndoableEdit DISCARD_ALL_EDITS = new AbstractUndoableEdit() {
    @Override
    public boolean canUndo() {
      return false;
    }

    @Override
    public boolean canRedo() {
      return false;
    }
  };

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(UndoRedoManager.class);

  protected PropertyChangeSupport propertySupport = new PropertyChangeSupport(this);

  /**
   * This flag is set to true when at least one significant UndoableEdit
   * has been added to the manager since the last call to discardAllEdits.
   */
  private boolean hasSignificantEdits = false;

  /**
   * This flag is set to true when an undo or redo operation is in progress.
   * The UndoRedoManager ignores all incoming UndoableEdit events while
   * this flag is true.
   */
  private boolean undoOrRedoInProgress;

  /**
   * The undo action instance.
   */
  private final UndoAction undoAction;
  /**
   * The redo action instance.
   */
  private final RedoAction redoAction;

  /**
   * Creates a new UndoRedoManager.
   */
  @Inject
  public UndoRedoManager() {
    undoAction = new UndoAction();
    redoAction = new RedoAction();
  }

  @Override
  public void discardAllEdits() {
    super.discardAllEdits();
    updateActions();
    setHasSignificantEdits(false);
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof SystemModelTransitionEvent) {
      handleSystemModelTransition((SystemModelTransitionEvent) event);
    }
  }

  private void handleSystemModelTransition(SystemModelTransitionEvent evt) {
    switch (evt.getStage()) {
      case UNLOADING:
        discardAllEdits();
        break;
      case LOADED:
        discardAllEdits();
        break;
      default:
      // Do nada.
    }
  }

  public void setHasSignificantEdits(boolean newValue) {
    boolean oldValue = hasSignificantEdits;
    hasSignificantEdits = newValue;
    firePropertyChange("hasSignificantEdits", oldValue, newValue);
  }

  /**
   * Returns true if at least one significant UndoableEdit
   * has been added since the last call to discardAllEdits.
   *
   * @return
   */
  public boolean hasSignificantEdits() {
    return hasSignificantEdits;
  }

  /**
   * If inProgress, inserts anEdit at indexOfNextAdd, and removes
   * any old edits that were at indexOfNextAdd or later. The die
   * method is called on each edit that is removed is sent, in the
   * reverse of the order the edits were added. Updates
   * indexOfNextAdd.
   * <p>
   * If not inProgress, acts as a CompoundEdit</p>
   * <p>
   * Regardless of inProgress, if undoOrRedoInProgress,
   * calls die on each edit that is sent.</p>
   *
   * @return
   * @see CompoundEdit#end
   * @see CompoundEdit#addEdit
   */
  @Override
  public boolean addEdit(UndoableEdit anEdit) {
    if (undoOrRedoInProgress) {
      anEdit.die();
      return true;
    }

    boolean success = super.addEdit(anEdit);

    updateActions();

    if (success && anEdit.isSignificant() && editToBeUndone() == anEdit) {
      setHasSignificantEdits(true);
    }

    return success;
  }

  /**
   * Gets the undo action for use as an
   *
   * @return Undo menu item.
   */
  public Action getUndoAction() {
    return undoAction;
  }

  /**
   * Gets the redo action for use as a Redo menu item.
   *
   * @return
   */
  public Action getRedoAction() {
    return redoAction;
  }

  /**
   * Updates the properties of the UndoAction
   * and of the RedoAction.
   */
  private void updateActions() {
    String label;

    if (canUndo()) {
      undoAction.setEnabled(true);
      label = getUndoPresentationName();
    }
    else {
      undoAction.setEnabled(false);
      label = ResourceBundleUtil.getBundle(I18nPlantOverview.MENU_PATH)
          .getString("undoRedoManager.undoAction.name");
    }

    undoAction.putValue(Action.NAME, label);
    undoAction.putValue(Action.SHORT_DESCRIPTION, label);

    if (canRedo()) {
      redoAction.setEnabled(true);
      label = getRedoPresentationName();
    }
    else {
      redoAction.setEnabled(false);
      label = ResourceBundleUtil.getBundle(I18nPlantOverview.MENU_PATH)
          .getString("undoRedoManager.redoAction.name");
    }

    redoAction.putValue(Action.NAME, label);
    redoAction.putValue(Action.SHORT_DESCRIPTION, label);
  }

  /**
   * Undoes the last edit event.
   * The UndoRedoManager ignores all incoming UndoableEdit events,
   * while undo is in progress.
   */
  @Override
  public void undo()
      throws CannotUndoException {
    undoOrRedoInProgress = true;

    try {
      super.undo();
    }
    finally {
      undoOrRedoInProgress = false;
      updateActions();
    }
  }

  /**
   * Redoes the last undone edit event.
   * The UndoRedoManager ignores all incoming UndoableEdit events,
   * while redo is in progress.
   */
  @Override
  public void redo()
      throws CannotUndoException {
    undoOrRedoInProgress = true;

    try {
      super.redo();
    }
    finally {
      undoOrRedoInProgress = false;
      updateActions();
    }
  }

  /**
   * Undoes or redoes the last edit event.
   * The UndoRedoManager ignores all incoming UndoableEdit events,
   * while undo or redo is in progress.
   */
  @Override
  public void undoOrRedo()
      throws CannotUndoException, CannotRedoException {
    undoOrRedoInProgress = true;

    try {
      super.undoOrRedo();
    }
    finally {
      undoOrRedoInProgress = false;
      updateActions();
    }
  }

  public void addPropertyChangeListener(PropertyChangeListener listener) {
    propertySupport.addPropertyChangeListener(listener);
  }

  public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
    propertySupport.addPropertyChangeListener(propertyName, listener);
  }

  public void removePropertyChangeListener(PropertyChangeListener listener) {
    propertySupport.removePropertyChangeListener(listener);
  }

  public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
    propertySupport.removePropertyChangeListener(propertyName, listener);
  }

  protected void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
    propertySupport.firePropertyChange(propertyName, oldValue, newValue);
  }

  protected void firePropertyChange(String propertyName, int oldValue, int newValue) {
    propertySupport.firePropertyChange(propertyName, oldValue, newValue);
  }

  protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
    propertySupport.firePropertyChange(propertyName, oldValue, newValue);
  }

  /**
   * Undo Action for use in a menu bar.
   */
  private class UndoAction
      extends AbstractAction {

    public UndoAction() {
      putValue(NAME, BUNDLE.getString("undoRedoManager.undoAction.name"));
      putValue(SHORT_DESCRIPTION, BUNDLE.getString("undoRedoManager.undoAction.shortDescription"));
      putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Z"));

      ImageIcon icon = ImageDirectory.getImageIcon("/menu/edit-undo.png");
      putValue(SMALL_ICON, icon);
      putValue(LARGE_ICON_KEY, icon);

      setEnabled(false);
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
      try {
        undo();
      }
      catch (CannotUndoException e) {
        LOG.debug("Cannot undo: {}", e);
      }
    }
  }

  /**
   * Redo Action for use in a menu bar.
   */
  private class RedoAction
      extends AbstractAction {

    public RedoAction() {
      putValue(NAME, BUNDLE.getString("undoRedoManager.redoAction.name"));
      putValue(SHORT_DESCRIPTION, BUNDLE.getString("undoRedoManager.redoAction.shortDescription"));
      putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Y"));

      ImageIcon icon = ImageDirectory.getImageIcon("/menu/edit-redo.png");
      putValue(SMALL_ICON, icon);
      putValue(LARGE_ICON_KEY, icon);

      setEnabled(false);
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
      try {
        redo();
      }
      catch (CannotRedoException e) {
        LOG.debug("Cannot redo: {}", e);
      }
    }
  }

}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/PortalManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

import org.opentcs.access.KernelServicePortal;
import org.opentcs.components.kernel.services.ServiceUnavailableException;

/**
 * Declares methods for managing a connection to a remote portal.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PortalManager {

  /**
   * Tries to establish a connection to the portal.
   *
   * @param mode The mode to use for the connection attempt.
   * @return {@code true} if, and only if, the connection was established successfully.
   */
  boolean connect(ConnectionMode mode);

  /**
   * Tells the portal manager the connection to the portal was lost.
   */
  void disconnect();

  /**
   * Checks whether a connection to the portal is established.
   *
   * @return {@code true} if, and only if, a connection to the portal is established.
   */
  boolean isConnected();

  /**
   * Returns the remote kernel client portal the manager is working with.
   *
   * @return The remote kernel client portal.
   */
  KernelServicePortal getPortal();

  /**
   * Returns a description for the current connection.
   *
   * @return A description for the current connection.
   */
  String getDescription();

  /**
   * Returns the host currently connected to.
   *
   * @return The host currently connected to, or {@code null}, if not connected.
   */
  String getHost();

  /**
   * Returns the port currently connected to.
   *
   * @return The port currently connected to, or {@code -1}, if not connected.
   */
  int getPort();

  /**
   * Defines the states in which a portal manager instance may be in.
   */
  public enum ConnectionState {

    /**
     * Indicates the portal manager is trying to connect to the remote portal.
     */
    CONNECTING,
    /**
     * Indicates the portal is connected and logged in to a remote portal, thus in a usable state.
     */
    CONNECTED,
    /**
     * Indicates the portal is disconnecting from the remote portal.
     */
    DISCONNECTING,
    /**
     * Indicates the portal is not connected to a remote portal.
     * While in this state, calls to the portal's service methods will result in a
     * {@link ServiceUnavailableException}.
     */
    DISCONNECTED;
  }

  /**
   * Defines the modes a portal manager uses to establish a connection to a portal.
   */
  public enum ConnectionMode {

    /**
     * Connect automatically by using a predefined set of connection parameters.
     */
    AUTO,
    /**
     * Connect manually by showing a dialog allowing to enter connection parameters.
     */
    MANUAL,
    /**
     * Connect to the portal we were previously connected to.
     */
    RECONNECT;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralController.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.util.ExplainedBoolean;

/**
 * Provides high-level methods for the system to control a peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralController
    extends Lifecycle {

  /**
   * Lets the peripheral device associated with this controller process the given job.
   * The callback is used to inform about the successful or failed completion of the job.
   *
   * @param job The job to process.
   * @param callback The callback to use.
   * @throws IllegalStateException If this peripheral device associated with this controller
   * cannot process the job.
   */
  void process(@Nonnull PeripheralJob job, @Nonnull PeripheralJobCallback callback)
      throws IllegalStateException;

  /**
   * Checks if the peripheral device would be able to process the given job, taking into account
   * its current state.
   *
   * @param job A job that might have to be processed.
   * @return An {@link ExplainedBoolean} telling if the peripheral device would be able to process
   * the job.
   */
  @Nonnull
  ExplainedBoolean canProcess(@Nonnull PeripheralJob job);

  /**
   * Sends a {@link PeripheralAdapterCommand} to the communication adapter.
   *
   * @param command The adapter command to be sent.
   */
  void sendCommAdapterCommand(@Nonnull PeripheralAdapterCommand command);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/event/package-info.java<|end_filename|>
/**
 * Interfaces and classes for event handling.
 */
package org.opentcs.util.event;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/FigureConstants.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import org.jhotdraw.draw.AttributeKey;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.model.ModelComponent;

/**
 * Constants that are relevant to figures.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface FigureConstants {

  /**
   * Key for figures to access their models.
   */
  AttributeKey<ModelComponent> MODEL = new AttributeKey<>("Model", ModelComponent.class);
  /**
   * Key for figures to access the origin.
   */
  AttributeKey<Origin> ORIGIN = new AttributeKey<>("Origin", Origin.class);
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/PeripheralOperationsProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.PeripheralOperationModel;

/**
 * A property that contains a list of Peripheral operations.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralOperationsProperty
    extends AbstractComplexProperty {
  
  public PeripheralOperationsProperty(ModelComponent model, List<PeripheralOperationModel> operations){
    super(model);
    fValue = operations;
  }

  @Override
  public Object getComparableValue() {
    return this.toString();
  }
  
  @Override
  public String toString(){
    return getValue().stream()
        .map(op -> op.getLocationName()+ ": " + op.getOperation())
        .collect(Collectors.joining(", "));
  }
  
  @Override
  public void copyFrom(Property property) {
    PeripheralOperationsProperty other = (PeripheralOperationsProperty) property;
    List<PeripheralOperationModel> items = new LinkedList<>(other.getValue());
    setValue(items);
  }
  
  @Override
  @SuppressWarnings("unchecked")
  public List<PeripheralOperationModel> getValue(){
    return (List) super.getValue();
  }

}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/logging/UncaughtExceptionLogger.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.logging;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An UncaughtExceptionHandler that logs everything not caught and then exits.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class UncaughtExceptionLogger
    implements Thread.UncaughtExceptionHandler {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(UncaughtExceptionLogger.class);
  /**
   * A flag indicating whether to exit on uncaught exceptions or not.
   */
  private final boolean doExit;

  /**
   * Creates a new UncaughtExceptionLogger.
   *
   * @param exitOnException A flag indicating whether to exit on uncaught
   * exceptions or not.
   */
  public UncaughtExceptionLogger(boolean exitOnException) {
    super();
    doExit = exitOnException;
  }

  @Override
  public void uncaughtException(Thread t, Throwable e) {
    // Log the exception, and then get out of here.
    LOG.error("Unhandled exception", e);
    if (doExit) {
      System.exit(1);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/NullContext.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import java.util.Set;
import javax.swing.JPopupMenu;

/**
 * A null context. Use this when no special context is required.
 *
 * @author <NAME> (<EMAIL>)
 */
public class NullContext
    implements UserObjectContext {

  @Override
  public JPopupMenu getPopupMenu(Set<UserObject> selectedUserObjects) {
    return new JPopupMenu();
  }

  @Override
  public boolean removed(UserObject userObject) {
    return true;
  }

  @Override
  public ContextType getType() {
    return ContextType.NULL;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/PointCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Triple;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A transfer object describing a point in the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PointCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * This point's position (in mm).
   */
  @Nonnull
  private Triple position = new Triple(0, 0, 0);
  /**
   * The vehicle's (assumed) orientation angle (-360..360) when it is at this position.
   * May be Double.NaN if an orientation angle is not defined for this point.
   */
  private double vehicleOrientationAngle = Double.NaN;
  /**
   * This point's type.
   */
  @Nonnull
  private Point.Type type = Point.Type.HALT_POSITION;
  /**
   * The information regarding the grahical representation of this point.
   */
  private Layout layout = new Layout();

  /**
   * Creates a new instance.
   *
   * @param name The name of this point.
   */
  public PointCreationTO(@Nonnull String name) {
    super(name);
  }

  private PointCreationTO(@Nonnull String name,
                          @Nonnull Map<String, String> properties,
                          @Nonnull Triple position,
                          double vehicleOrientationAngle,
                          @Nonnull Point.Type type,
                          @Nonnull Layout layout) {
    super(name, properties);
    this.position = requireNonNull(position, "position");
    this.vehicleOrientationAngle = vehicleOrientationAngle;
    this.type = requireNonNull(type, "type");
    this.layout = requireNonNull(layout, "layout");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new name.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public PointCreationTO withName(@Nonnull String name) {
    return new PointCreationTO(name,
                               getModifiableProperties(),
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  /**
   * Returns the position of this point (in mm).
   *
   * @return The position of this point (in mm).
   */
  @Nonnull
  public Triple getPosition() {
    return position;
  }

  /**
   * Creates a copy of this object with the given position (in mm).
   *
   * @param position The new position.
   * @return A copy of this object, differing in the given position.
   */
  public PointCreationTO withPosition(@Nonnull Triple position) {
    return new PointCreationTO(getName(),
                               getModifiableProperties(),
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  /**
   * Returns a vehicle's orientation angle at this position.
   * (-360..360, or {@code Double.NaN}, if an orientation angle is not specified for this point.)
   *
   * @return The vehicle's orientation angle when it's at this position.
   */
  public double getVehicleOrientationAngle() {
    return vehicleOrientationAngle;
  }

  /**
   * Creates a copy of this object with the vehicle's (assumed) orientation angle when it's at this position.
   * Allowed value range: [-360..360], or {@code Double.NaN} to indicate that there is no specific
   * orientation angle for this point.
   *
   * @param vehicleOrientationAngle The new angle.
   * @return A copy of this object, differing in the given angle.
   */
  public PointCreationTO withVehicleOrientationAngle(double vehicleOrientationAngle) {
    checkArgument(Double.isNaN(vehicleOrientationAngle)
        || (vehicleOrientationAngle >= -360.0 || vehicleOrientationAngle <= 360.0),
                  "vehicleOrientationAngle not in [-360..360]: " + vehicleOrientationAngle);
    return new PointCreationTO(getName(),
                               getModifiableProperties(),
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  /**
   * Returns the type of this point.
   *
   * @return The type of this point.
   */
  @Nonnull
  public Point.Type getType() {
    return type;
  }

  /**
   * Creates a copy of this object with the given type.
   *
   * @param type The new type.
   * @return A copy of this object, differing in the given type.
   */
  public PointCreationTO withType(@Nonnull Point.Type type) {
    return new PointCreationTO(getName(),
                               getProperties(),
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public PointCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new PointCreationTO(getName(),
                               properties,
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public PointCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new PointCreationTO(getName(),
                               propertiesWith(key, value),
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  /**
   * Returns the information regarding the grahical representation of this point.
   *
   * @return The information regarding the grahical representation of this point.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PointCreationTO withLayout(Layout layout) {
    return new PointCreationTO(getName(),
                               getModifiableProperties(),
                               position,
                               vehicleOrientationAngle,
                               type,
                               layout);
  }

  @Override
  public String toString() {
    return "PointCreationTO{"
        + "name=" + getName()
        + ", position=" + position
        + ", vehicleOrientationAngle=" + vehicleOrientationAngle
        + ", type=" + type
        + ", layout=" + layout
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Contains information regarding the grahical representation of a point.
   */
  public static class Layout
      implements Serializable {

    /**
     * The coordinates at which the point is to be drawn (in mm).
     */
    private final Couple position;
    /**
     * The offset of the label's position to the point's position (in lu).
     */
    private final Couple labelOffset;
    /**
     * The ID of the layer on which the point is to be drawn.
     */
    private final int layerId;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(new Couple(0, 0), new Couple(0, 0), 0);
    }

    /**
     * Creates a new instance.
     *
     * @param position The coordinates at which the point is to be drawn (in mm).
     * @param labelOffset The offset of the label's position to the point's position (in lu).
     * @param layerId The ID of the layer on which the point is to be drawn.
     */
    public Layout(Couple position,
                  Couple labelOffset,
                  int layerId) {
      this.position = requireNonNull(position, "position");
      this.labelOffset = requireNonNull(labelOffset, "labelOffset");
      this.layerId = layerId;
    }

    /**
     * Returns the coordinates at which the point is to be drawn (in mm).
     *
     * @return The coordinates at which the point is to be drawn (in mm).
     */
    public Couple getPosition() {
      return position;
    }

    /**
     * Creates a copy of this object, with the given position.
     *
     * @param position The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withPosition(Couple position) {
      return new Layout(position,
                        labelOffset,
                        layerId);
    }

    /**
     * Returns the offset of the label's position to the point's position (in lu).
     *
     * @return The offset of the label's position to the point's position (in lu).
     */
    public Couple getLabelOffset() {
      return labelOffset;
    }

    /**
     * Creates a copy of this object, with the given X label offset.
     *
     * @param labelOffset The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLabelOffset(Couple labelOffset) {
      return new Layout(position,
                        labelOffset,
                        layerId);
    }

    /**
     * Returns the ID of the layer on which the point is to be drawn.
     *
     * @return The layer ID.
     */
    public int getLayerId() {
      return layerId;
    }

    /**
     * Creates a copy of this object, with the given layer ID.
     *
     * @param layerId The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLayerId(int layerId) {
      return new Layout(position,
                        labelOffset,
                        layerId);
    }

    @Override
    public String toString() {
      return "Layout{"
          + "position=" + position
          + ", labelOffset=" + labelOffset
          + ", layerId=" + layerId
          + '}';
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/action/ViewActionMap.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.ActionMap;
import org.opentcs.guing.application.OpenTCSView;
import org.opentcs.guing.application.action.actions.CreatePeripheralJobAction;
import org.opentcs.guing.application.action.actions.CreateTransportOrderAction;
import org.opentcs.guing.application.action.actions.FindVehicleAction;
import org.opentcs.guing.application.action.actions.PauseAllVehiclesAction;
import org.opentcs.guing.application.action.actions.ResumeAllVehiclesAction;
import org.opentcs.guing.application.action.app.AboutAction;
import org.opentcs.guing.application.action.file.ModelPropertiesAction;
import org.opentcs.guing.application.action.file.SaveModelAction;
import org.opentcs.guing.application.action.file.SaveModelAsAction;
import org.opentcs.guing.application.action.view.AddDrawingViewAction;
import org.opentcs.guing.application.action.view.AddTransportOrderSequenceViewAction;
import org.opentcs.guing.application.action.view.AddTransportOrderViewAction;
import org.opentcs.guing.application.action.view.RestoreDockingLayoutAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.DeleteAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.SelectAllAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;
import org.opentcs.thirdparty.jhotdraw.application.action.file.CloseFileAction;

/**
 * A custom ActionMap for the plant overview application.
 *
 * @author Stefan Walter (Fraunhofer IML)
 */
public class ViewActionMap
    extends ActionMap {

  /**
   * Creates a new instance.
   *
   * @param view The openTCS view
   * @param undoRedoManager The undo redo manager
   * @param actionFactory The action factory
   * @param createTransportOrderAction The action to create transport orders
   * @param findVehicleAction The action to find vehicles
   * @param pauseAllVehiclesAction The action to pause all vehicles
   * @param resumeAllVehiclesAction The action to resume all vehicles
   * @param aboutAction The action to show the about window
   * @param modelPropertiesAction The action to show some model properties.
   * @param createPeripheralJobAction The action to create peripheral jobs.
   */
  @Inject
  public ViewActionMap(OpenTCSView view,
                       UndoRedoManager undoRedoManager,
                       ActionFactory actionFactory,
                       CreateTransportOrderAction createTransportOrderAction,
                       FindVehicleAction findVehicleAction,
                       PauseAllVehiclesAction pauseAllVehiclesAction,
                       ResumeAllVehiclesAction resumeAllVehiclesAction,
                       AboutAction aboutAction,
                       ModelPropertiesAction modelPropertiesAction,
                       CreatePeripheralJobAction createPeripheralJobAction) {
    requireNonNull(view, "view");
    requireNonNull(undoRedoManager, "undoRedoManager");
    requireNonNull(actionFactory, "actionFactory");
    requireNonNull(createTransportOrderAction, "createTransportOrderAction");
    requireNonNull(findVehicleAction, "findVehicleAction");
    requireNonNull(pauseAllVehiclesAction, "pauseAllVehiclesAction");
    requireNonNull(resumeAllVehiclesAction, "resumeAllVehiclesAction");
    requireNonNull(aboutAction, "aboutAction");
    requireNonNull(createPeripheralJobAction, "createPeripheralJobAction");

    // --- Menu File ---
    put(SaveModelAction.ID, new SaveModelAction(view));
    put(SaveModelAsAction.ID, new SaveModelAsAction(view));
    put(ModelPropertiesAction.ID, modelPropertiesAction);
    put(CloseFileAction.ID, new CloseFileAction(view));

    // --- Menu Edit ---
    // Undo, Redo
    put(UndoRedoManager.UNDO_ACTION_ID, undoRedoManager.getUndoAction());
    put(UndoRedoManager.REDO_ACTION_ID, undoRedoManager.getRedoAction());
    // Cut, Copy, Paste, Duplicate, Delete
    put(DeleteAction.ID, new DeleteAction());
    // Select all
    put(SelectAllAction.ID, new SelectAllAction());

    // --- Menu Actions ---
    // Menu item Actions -> Create ...
    put(CreateTransportOrderAction.ID, createTransportOrderAction);
    put(CreatePeripheralJobAction.ID, createPeripheralJobAction);

    // --- Menu View ---
    // Menu View -> Add drawing view
    put(AddDrawingViewAction.ID, new AddDrawingViewAction(view));

    // Menu View -> Add transport order view
    put(AddTransportOrderViewAction.ID, new AddTransportOrderViewAction(view));

    // Menu View -> Add transport order sequence view
    put(AddTransportOrderSequenceViewAction.ID, new AddTransportOrderSequenceViewAction(view));

    put(RestoreDockingLayoutAction.ID, new RestoreDockingLayoutAction(view));

    put(FindVehicleAction.ID, findVehicleAction);
    put(PauseAllVehiclesAction.ID, pauseAllVehiclesAction);
    put(ResumeAllVehiclesAction.ID, resumeAllVehiclesAction);

    // --- Menu Help ---
    put(AboutAction.ID, aboutAction);
  }

}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/LayoutToModelCoordinateUndoActivity.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus;

import com.google.inject.assistedinject.Assisted;
import javax.inject.Inject;
import org.opentcs.guing.components.properties.CoordinateUndoActivity;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayoutToModelCoordinateUndoActivity
    extends CoordinateUndoActivity {

  @Inject
  public LayoutToModelCoordinateUndoActivity(@Assisted CoordinateProperty property,
                                             ModelManager modelManager) {
    super(property, modelManager);
  }

  @Override
  public String getPresentationName() {
    return ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MISC_PATH)
        .getString("layoutToModelCoordinateUndoActivity.presentationName");
  }

  @Override
  protected void saveTransformBeforeModification() {
  }

  @Override
  protected void saveTransformForUndo() {
  }

  @Override
  protected void saveTransformForRedo() {
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/assignment/AssignFreeOrdersPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_ASSIGNED_TO_VEHICLE;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_DISPATCHING_DEFERRED;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_DISPATCHING_RESUMED;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_RESERVED_FOR_VEHICLE;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.OrderReservationPool;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.phase.AssignmentState;
import org.opentcs.strategies.basic.dispatching.phase.CandidateFilterResult;
import org.opentcs.strategies.basic.dispatching.phase.OrderFilterResult;
import org.opentcs.strategies.basic.dispatching.phase.VehicleFilterResult;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeOrderCandidateComparator;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeOrderComparator;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeVehicleCandidateComparator;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeVehicleComparator;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.orders.CompositeTransportOrderSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.orders.IsFreelyDispatchableToAnyVehicle;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.IsAvailableForAnyOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Assigns transport orders to vehicles that are currently not processing any and are not bound to
 * any order sequences.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignFreeOrdersPhase
    implements Phase {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AssignFreeOrdersPhase.class);
  /**
   * The object service
   */
  private final TCSObjectService objectService;
  /**
   * The Router instance calculating route costs.
   */
  private final Router router;
  /**
   * Stores reservations of orders for vehicles.
   */
  private final OrderReservationPool orderReservationPool;
  /**
   * Defines the order of vehicles when there are less vehicles than transport orders.
   */
  private final Comparator<Vehicle> vehicleComparator;
  /**
   * Defines the order of transport orders when there are less transport orders than vehicles.
   */
  private final Comparator<TransportOrder> orderComparator;
  /**
   * Sorts candidates when looking for a transport order to be assigned to a vehicle.
   */
  private final Comparator<AssignmentCandidate> orderCandidateComparator;
  /**
   * Sorts candidates when looking for a vehicle to be assigned to a transport order.
   */
  private final Comparator<AssignmentCandidate> vehicleCandidateComparator;
  /**
   * A collection of predicates for filtering vehicles.
   */
  private final CompositeVehicleSelectionFilter vehicleSelectionFilter;

  private final IsAvailableForAnyOrder isAvailableForAnyOrder;

  private final IsFreelyDispatchableToAnyVehicle isFreelyDispatchableToAnyVehicle;
  /**
   * A collection of predicates for filtering transport orders.
   */
  private final CompositeTransportOrderSelectionFilter transportOrderSelectionFilter;
  /**
   * A collection of predicates for filtering assignment candidates.
   */
  private final CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter;

  private final TransportOrderUtil transportOrderUtil;

  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public AssignFreeOrdersPhase(
      TCSObjectService objectService,
      Router router,
      OrderReservationPool orderReservationPool,
      CompositeVehicleComparator vehicleComparator,
      CompositeOrderComparator orderComparator,
      CompositeOrderCandidateComparator orderCandidateComparator,
      CompositeVehicleCandidateComparator vehicleCandidateComparator,
      CompositeVehicleSelectionFilter vehicleSelectionFilter,
      IsAvailableForAnyOrder isAvailableForAnyOrder,
      IsFreelyDispatchableToAnyVehicle isFreelyDispatchableToAnyVehicle,
      CompositeTransportOrderSelectionFilter transportOrderSelectionFilter,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      TransportOrderUtil transportOrderUtil) {
    this.router = requireNonNull(router, "router");
    this.objectService = requireNonNull(objectService, "objectService");
    this.orderReservationPool = requireNonNull(orderReservationPool, "orderReservationPool");
    this.vehicleComparator = requireNonNull(vehicleComparator, "vehicleComparator");
    this.orderComparator = requireNonNull(orderComparator, "orderComparator");
    this.orderCandidateComparator = requireNonNull(orderCandidateComparator,
                                                   "orderCandidateComparator");
    this.vehicleCandidateComparator = requireNonNull(vehicleCandidateComparator,
                                                     "vehicleCandidateComparator");
    this.vehicleSelectionFilter = requireNonNull(vehicleSelectionFilter, "vehicleSelectionFilter");
    this.isAvailableForAnyOrder = requireNonNull(isAvailableForAnyOrder, "isAvailableForAnyOrder");
    this.isFreelyDispatchableToAnyVehicle = requireNonNull(isFreelyDispatchableToAnyVehicle,
                                                           "isFreelyDispatchableToAnyVehicle");
    this.transportOrderSelectionFilter = requireNonNull(transportOrderSelectionFilter,
                                                        "transportOrderSelectionFilter");
    this.assignmentCandidateSelectionFilter = requireNonNull(assignmentCandidateSelectionFilter,
                                                             "assignmentCandidateSelectionFilter");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    Map<Boolean, List<VehicleFilterResult>> vehiclesSplitByFilter
        = objectService.fetchObjects(Vehicle.class, isAvailableForAnyOrder)
            .stream()
            .map(order -> new VehicleFilterResult(order, vehicleSelectionFilter.apply(order)))
            .collect(Collectors.partitioningBy(filterResult -> !filterResult.isFiltered()));

    Collection<Vehicle> availableVehicles = vehiclesSplitByFilter.get(Boolean.TRUE).stream()
        .map(VehicleFilterResult::getVehicle)
        .collect(Collectors.toList());

    if (availableVehicles.isEmpty()) {
      LOG.debug("No vehicles available, skipping potentially expensive fetching of orders.");
      return;
    }

    // Select only dispatchable orders first, then apply the composite filter, handle
    // the orders that can be tried as usual and mark the others as filtered (if they aren't, yet).
    Map<Boolean, List<OrderFilterResult>> ordersSplitByFilter
        = objectService.fetchObjects(TransportOrder.class, isFreelyDispatchableToAnyVehicle)
            .stream()
            .map(order -> new OrderFilterResult(order, transportOrderSelectionFilter.apply(order)))
            .collect(Collectors.partitioningBy(filterResult -> !filterResult.isFiltered()));

    markNewlyFilteredOrders(ordersSplitByFilter.get(Boolean.FALSE));

    tryAssignments(availableVehicles,
                   ordersSplitByFilter.get(Boolean.TRUE).stream()
                       .map(OrderFilterResult::getOrder)
                       .collect(Collectors.toList()));
  }

  private void tryAssignments(Collection<Vehicle> availableVehicles,
                              Collection<TransportOrder> availableOrders) {
    LOG.debug("Available for dispatching: {} transport orders and {} vehicles.",
              availableOrders.size(),
              availableVehicles.size());

    AssignmentState assignmentState = new AssignmentState();
    if (availableVehicles.size() < availableOrders.size()) {
      availableVehicles.stream()
          .sorted(vehicleComparator)
          .forEach(vehicle -> tryAssignOrder(vehicle, availableOrders, assignmentState));
    }
    else {
      availableOrders.stream()
          .sorted(orderComparator)
          .forEach(order -> tryAssignVehicle(order, availableVehicles, assignmentState));
    }

    assignmentState.getFilteredOrders().values().stream()
        .filter(filterResult -> !assignmentState.wasAssignedToVehicle(filterResult.getOrder()))
        .filter(this::filterReasonsChanged)
        .forEach(this::doMarkAsFiltered);

    availableOrders.stream()
        .filter(order -> (!assignmentState.wasFiltered(order)
                          && !assignmentState.wasAssignedToVehicle(order)))
        .filter(this::markedAsFiltered)
        .forEach(this::doUnmarkAsFiltered);
  }

  private void markNewlyFilteredOrders(Collection<OrderFilterResult> filterResults) {
    filterResults.stream()
        .filter(filterResult -> (!markedAsFiltered(filterResult.getOrder())
                                 || filterReasonsChanged(filterResult)))
        .forEach(filterResult -> doMarkAsFiltered(filterResult));
  }

  private boolean markedAsFiltered(TransportOrder order) {
    return lastRelevantDeferredHistoryEntry(order).isPresent();
  }

  private Optional<ObjectHistory.Entry> lastRelevantDeferredHistoryEntry(TransportOrder order) {
    return order.getHistory().getEntries().stream()
        .filter(entry -> equalsAny(entry.getEventCode(),
                                   ORDER_DISPATCHING_DEFERRED,
                                   ORDER_DISPATCHING_RESUMED))
        .reduce((firstEntry, secondEntry) -> secondEntry)
        .filter(entry -> entry.getEventCode().equals(ORDER_DISPATCHING_DEFERRED));
  }

  @SuppressWarnings("unchecked")
  private boolean filterReasonsChanged(OrderFilterResult filterResult) {
    Collection<String> newReasons = filterResult.getFilterReasons();
    Collection<String> oldReasons = lastRelevantDeferredHistoryEntry(filterResult.getOrder())
        .map(entry -> (Collection<String>) entry.getSupplement())
        .orElse(new ArrayList<>());

    return newReasons.size() != oldReasons.size()
        || !newReasons.containsAll(oldReasons);
  }

  private void doMarkAsFiltered(OrderFilterResult filterResult) {
    objectService.appendObjectHistoryEntry(
        filterResult.getOrder().getReference(),
        new ObjectHistory.Entry(
            ORDER_DISPATCHING_DEFERRED,
            Collections.unmodifiableList(new ArrayList<>(filterResult.getFilterReasons()))
        )
    );
  }

  private void doUnmarkAsFiltered(TransportOrder order) {
    objectService.appendObjectHistoryEntry(
        order.getReference(),
        new ObjectHistory.Entry(
            ORDER_DISPATCHING_RESUMED,
            Collections.unmodifiableList(new ArrayList<>())
        )
    );
  }

  private boolean equalsAny(String string, String... others) {
    return Arrays.asList(others).stream()
        .anyMatch(other -> string.equals(other));
  }

  private void tryAssignOrder(Vehicle vehicle,
                              Collection<TransportOrder> availableOrders,
                              AssignmentState assignmentState) {
    LOG.debug("Trying to find transport order for vehicle '{}'...", vehicle.getName());

    Point vehiclePosition = objectService.fetchObject(Point.class, vehicle.getCurrentPosition());

    Map<Boolean, List<CandidateFilterResult>> ordersSplitByFilter
        = availableOrders.stream()
            .filter(order -> (!assignmentState.wasAssignedToVehicle(order)
                              && orderAssignableToVehicle(order, vehicle)))
            .map(order -> computeCandidate(vehicle, vehiclePosition, order))
            .filter(optCandidate -> optCandidate.isPresent())
            .map(optCandidate -> optCandidate.get())
            .map(candidate -> new CandidateFilterResult(candidate, assignmentCandidateSelectionFilter.apply(candidate)))
            .collect(Collectors.partitioningBy(filterResult -> !filterResult.isFiltered()));

    ordersSplitByFilter.get(Boolean.FALSE).stream()
        .map(CandidateFilterResult::toFilterResult)
        .forEach(filterResult -> assignmentState.addFilteredOrder(filterResult));

    ordersSplitByFilter.get(Boolean.TRUE).stream()
        .map(CandidateFilterResult::getCandidate)
        .sorted(orderCandidateComparator)
        .findFirst()
        .ifPresent(candidate -> assignOrder(candidate, assignmentState));
  }

  private void tryAssignVehicle(TransportOrder order,
                                Collection<Vehicle> availableVehicles,
                                AssignmentState assignmentState) {
    LOG.debug("Trying to find vehicle for transport order '{}'...", order.getName());

    Map<Boolean, List<CandidateFilterResult>> ordersSplitByFilter
        = availableVehicles.stream()
            .filter(vehicle -> (!assignmentState.wasAssignedToOrder(vehicle)
                                && orderAssignableToVehicle(order, vehicle)))
            .map(vehicle -> computeCandidate(vehicle,
                                             objectService.fetchObject(Point.class,
                                                                       vehicle.getCurrentPosition()),
                                             order))
            .filter(optCandidate -> optCandidate.isPresent())
            .map(optCandidate -> optCandidate.get())
            .map(candidate -> new CandidateFilterResult(candidate, assignmentCandidateSelectionFilter.apply(candidate)))
            .collect(Collectors.partitioningBy(filterResult -> !filterResult.isFiltered()));

    ordersSplitByFilter.get(Boolean.FALSE).stream()
        .map(CandidateFilterResult::toFilterResult)
        .forEach(filterResult -> assignmentState.addFilteredOrder(filterResult));

    ordersSplitByFilter.get(Boolean.TRUE).stream()
        .map(CandidateFilterResult::getCandidate)
        .sorted(vehicleCandidateComparator)
        .findFirst()
        .ifPresent(candidate -> assignOrder(candidate, assignmentState));
  }

  private void assignOrder(AssignmentCandidate candidate, AssignmentState assignmentState) {
    // If the vehicle currently has a (dispensable) order, we may not assign the new one here
    // directly, but must abort the old one (DefaultDispatcher.abortOrder()) and wait for the
    // vehicle's ProcState to become IDLE.
    if (candidate.getVehicle().getTransportOrder() == null) {
      LOG.debug("Assigning transport order '{}' to vehicle '{}'...",
                candidate.getTransportOrder().getName(),
                candidate.getVehicle().getName());
      doMarkAsAssigned(candidate.getTransportOrder(), candidate.getVehicle());
      transportOrderUtil.assignTransportOrder(candidate.getVehicle(),
                                              candidate.getTransportOrder(),
                                              candidate.getDriveOrders());
      assignmentState.getAssignedCandidates().add(candidate);
    }
    else {
      LOG.debug("Reserving transport order '{}' for vehicle '{}'...",
                candidate.getTransportOrder().getName(),
                candidate.getVehicle().getName());
      // Remember that the new order is reserved for this vehicle.
      doMarkAsReserved(candidate.getTransportOrder(), candidate.getVehicle());
      orderReservationPool.addReservation(candidate.getTransportOrder().getReference(),
                                          candidate.getVehicle().getReference());
      assignmentState.getReservedCandidates().add(candidate);
      transportOrderUtil.abortOrder(candidate.getVehicle(), false, false, false);
    }
  }

  private void doMarkAsAssigned(TransportOrder order, Vehicle vehicle) {
    objectService.appendObjectHistoryEntry(
        order.getReference(),
        new ObjectHistory.Entry(ORDER_ASSIGNED_TO_VEHICLE, vehicle.getName())
    );
  }

  private void doMarkAsReserved(TransportOrder order, Vehicle vehicle) {
    objectService.appendObjectHistoryEntry(
        order.getReference(),
        new ObjectHistory.Entry(ORDER_RESERVED_FOR_VEHICLE, vehicle.getName())
    );
  }

  private Optional<AssignmentCandidate> computeCandidate(Vehicle vehicle,
                                                         Point vehiclePosition,
                                                         TransportOrder order) {
    return router.getRoute(vehicle, vehiclePosition, order)
        .map(driveOrders -> new AssignmentCandidate(vehicle, order, driveOrders));
  }

  private boolean orderAssignableToVehicle(TransportOrder order, Vehicle vehicle) {
    return order.getIntendedVehicle() == null
        || Objects.equals(order.getIntendedVehicle(), vehicle.getReference());
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/ConnectableModelComponent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.List;
import org.opentcs.guing.model.elements.AbstractConnection;

/**
 * A {@link ModelComponent} that can be connected with another model component.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface ConnectableModelComponent
    extends ModelComponent {

  /**
   * Adds a connection.
   *
   * @param connection The connection to be added.
   */
  void addConnection(AbstractConnection connection);

  /**
   * Returns all connections.
   *
   * @return All connections.
   */
  List<AbstractConnection> getConnections();

  /**
   * Removes a connection.
   *
   * @param connection The connection to be removed.
   */
  void removeConnection(AbstractConnection connection);
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/package-info.java<|end_filename|>
/**
 * Classes for emulating the behaviour of a physical vehicle.
 */
package org.opentcs.virtualvehicle;


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/documentation/CreateTransportOrderSequenceTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.documentation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.access.to.order.DestinationCreationTO;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;

/**
 * Test for the developers asciidoc documentation to show how a tranport order sequence is created.
 * This test has no meaning and it just exists for the documentation to refer to and to guarantee
 * an example that compiles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CreateTransportOrderSequenceTest {

  private TransportOrderService orderService;
  private DispatcherService dispService;

  @Before
  public void setUp() {
    orderService = mock(InternalTransportOrderService.class);
    dispService = mock(DispatcherService.class);
    when(orderService.createOrderSequence(any(OrderSequenceCreationTO.class)))
        .thenReturn(new OrderSequence("OrderSequence"));
    when(orderService.createTransportOrder(any(TransportOrderCreationTO.class)))
        .thenReturn(new TransportOrder(
            "Transportorder",
            Collections.singletonList(new DriveOrder(
                new DriveOrder.Destination(getSampleDestinationLocation().getReference())
                    .withOperation("some operation")))));
  }

  @Test
  public void shouldCreateTransportOrderSequence() {
    // tag::documentation_createTransportOrderSequence[]
    // The transport order service instance we're working with
    TransportOrderService transportOrderService = getATransportOrderServiceReference();

    // The dispatcher service instance we're working with
    DispatcherService dispatcherService = getADispatcherServiceReference();

    // Create an order sequence description with a unique name:
    OrderSequenceCreationTO sequenceTO
        = new OrderSequenceCreationTO("MyOrderSequence");
    // Optionally, express that the actual/full name of the sequence should be
    // generated by the kernel.
    sequenceTO = sequenceTO.withIncompleteName(true);
    // Optionally, set the sequence's failure-fatal flag:
    sequenceTO = sequenceTO.withFailureFatal(true);

    // Create the order sequence:
    OrderSequence orderSequence = transportOrderService.createOrderSequence(sequenceTO);

    // Set up the transport order as usual,
    // but add the wrapping sequence's name:
    List<DestinationCreationTO> destinations = new ArrayList<>();
    destinations.add(new DestinationCreationTO("Some location name",
                                               "Some operation"));
    TransportOrderCreationTO orderTO
        = new TransportOrderCreationTO("MyOrder-" + UUID.randomUUID(),
                                       destinations)
            .withWrappingSequence(orderSequence.getName());

    // Create the transport order:
    TransportOrder order = transportOrderService.createTransportOrder(orderTO);

    // Create and add more orders as necessary.
    // Eventually, set the order sequence's complete flag to indicate that more
    // transport orders will not be added to it.
    transportOrderService.markOrderSequenceComplete(orderSequence.getReference());

    // Trigger the dispatch process for the created order sequence.
    dispatcherService.dispatch();
    // end::documentation_createTransportOrderSequence[]
  }

  private Location getSampleDestinationLocation() {
    return new Location("Location",
                        new LocationType("LocationType").getReference());
  }

  private TransportOrderService getATransportOrderServiceReference() {
    return orderService;
  }

  private DispatcherService getADispatcherServiceReference() {
    return dispService;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/course/CoordinateBasedDrawingMethod.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.course;

/**
 * A drawing method where the position of a figure and the real position are in relation 
 * to each other.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class CoordinateBasedDrawingMethod
    implements DrawingMethod {

  /**
   * The origin point.
   */
  protected Origin fOrigin;

  /**
   * Creates a new instance of CoordinateBasedDrawingMethod
   */
  public CoordinateBasedDrawingMethod() {
    fOrigin = new Origin();
  }

  @Override
  public Origin getOrigin() {
    return fOrigin;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/event/EventLogger.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.event;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EventLogger
    implements EventHandler,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(EventLogger.class);
  /**
   * Where we register for events.
   */
  private final EventSource eventSource;
  /**
   * Whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public EventLogger(@ApplicationEventBus EventSource eventSource) {
    this.eventSource = requireNonNull(eventSource, "eventSource");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventSource.subscribe(this);

    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventSource.unsubscribe(this);

    initialized = false;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void onEvent(Object event) {
    LOG.debug("Received event: {}", event);
  }

}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/commands/FinishJobProcessingCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback.commands;

import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;

/**
 * A command to trigger the comm adapter in manual mode and finish the job the simulated peripheral
 * device is currently processing.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FinishJobProcessingCommand
    implements PeripheralAdapterCommand {

  /**
   * Whether to fail the execution of the job the (simulated) peripheral device is currently
   * processing.
   */
  private final boolean failJob;

  /**
   * Creates a new instance.
   *
   * @param failJob Whether to fail the execution of the job the (simulated) peripheral device is
   * currently processing.
   */
  public FinishJobProcessingCommand(boolean failJob) {
    this.failJob = failJob;
  }

  @Override
  public void execute(PeripheralCommAdapter adapter) {
    if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
      return;
    }

    LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
    loopbackAdapter.triggerJobProcessing(failJob);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/FilterButton.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import java.awt.event.ActionEvent;
import javax.swing.ImageIcon;
import javax.swing.JToggleButton;
import javax.swing.RowFilter;
import javax.swing.table.TableModel;

/**
 * A button for filtering table entries.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class FilterButton
    extends JToggleButton {

  /**
   * The sorter to apply the filter to.
   */
  private final FilteredRowSorter<? extends TableModel> sorter;
  /**
   * The filter to apply.
   */
  private final RowFilter<Object, Object> filter;

  /**
   * Creates a new instance.
   *
   * @param icon The image that the button should display
   * @param filter The Filter to apply.
   * @param sorter The row sorter to apply the filter to.
   */
  public FilterButton(ImageIcon icon,
                      RowFilter<Object, Object> filter,
                      FilteredRowSorter<? extends TableModel> sorter) {
    super(icon);
    this.sorter = sorter;
    this.filter = filter;

    addActionListener((ActionEvent e) -> changed());
    setSelected(true);
  }

  /**
   * Called when the button has changed.
   */
  private void changed() {
    if (isSelected()) {
      sorter.removeRowFilter(filter);
    }
    else {
      sorter.addRowFilter(filter);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/test/java/org/opentcs/guing/components/properties/type/SpeedPropertyTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;
import org.opentcs.guing.components.properties.type.SpeedProperty.Unit;
import org.opentcs.guing.model.AbstractModelComponent;

/**
 * A test for a speed property.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class SpeedPropertyTest {

  private SpeedProperty property;

  @ParameterizedTest
  @ValueSource(strings = {"mm/s", "m/s", "km/h"})
  public void testValidUnits(String unit) {
    property = new SpeedProperty(new DummyComponent());
    assertTrue(property.isPossibleUnit(unit));
  }

  @ParameterizedTest
  @MethodSource("paramsFactory")
  public void testPropertyConversion(Unit unit, Object result) {
    property = new SpeedProperty(new DummyComponent(), 10000.0, Unit.MM_S);
    property.convertTo(unit);
    assertEquals(result, property.getValue());
    assertEquals(unit, property.getUnit());
  }

  @Test
  public void testPropertyRange() {
    property = new SpeedProperty(new DummyComponent());
    assertEquals(0, property.getValidRange().getMin(), 0);
    assertEquals(Double.MAX_VALUE, property.getValidRange().getMax(), 0);
  }

  public static Object[][] paramsFactory() {
    return new Object[][] {{Unit.MM_S, 10000.0},
                           {Unit.M_S, 10.0},
                           {Unit.KM_H, 36.0}};
  }

  private class DummyComponent
      extends AbstractModelComponent {
  }
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/UserAccountProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.util.Set;

/**
 * Provides user account data.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface UserAccountProvider {

  Set<UserAccount> getUserAccounts();
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/extensions/controlcenter/vehicles/VehicleEntry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.controlcenter.vehicles;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.drivers.vehicle.VehicleCommAdapterFactory;
import org.opentcs.drivers.vehicle.VehicleProcessModel;

/**
 * Represents a {@link Vehicle} in the {@link VehicleEntryPool}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleEntry
    implements PropertyChangeListener {

  /**
   * The vehicle this entry represents.
   */
  private final Vehicle vehicle;
  /**
   * Used for implementing property change events.
   */
  private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  /**
   * The process model for the vehicle.
   */
  private VehicleProcessModel processModel;
  /**
   * The comm adapter factory for this vehicle.
   */
  private VehicleCommAdapterFactory commAdapterFactory = new NullVehicleCommAdapterFactory();
  /**
   * The comm adapter that is attached to this vehicle.
   */
  private VehicleCommAdapter commAdapter;

  /**
   * Creates a vehicle entry.
   *
   * @param vehicle The vehicle this entry represents.
   */
  public VehicleEntry(Vehicle vehicle) {
    this.vehicle = requireNonNull(vehicle, "vehicle");
    this.processModel = new VehicleProcessModel(vehicle);
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if (!(evt.getSource() instanceof VehicleProcessModel)) {
      return;
    }

    pcs.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
  }

  /**
   * Add a property change listener.
   *
   * @param listener The listener to add.
   */
  public void addPropertyChangeListener(PropertyChangeListener listener) {
    pcs.addPropertyChangeListener(listener);
  }

  /**
   * Remove a property change listener.
   *
   * @param listener The listener to remove.
   */
  public void removePropertyChangeListener(PropertyChangeListener listener) {
    pcs.removePropertyChangeListener(listener);
  }

  /**
   * Returns the vehicle that is represented by this entry.
   *
   * @return The vehicle that is represented by this entry.
   */
  @Nonnull
  public Vehicle getVehicle() {
    return vehicle;
  }

  /**
   * Returns the name of the vehicle that is represented by this entry.
   *
   * @return The name of the vehicle that is represented by this entry.
   */
  @Nonnull
  public String getVehicleName() {
    return vehicle.getName();
  }

  /**
   * Returns the process model of the vehicle that is represented by this entry.
   *
   * @return The process model of the vehicle that is represented by this entry.
   */
  @Nonnull
  public VehicleProcessModel getProcessModel() {
    return processModel;
  }

  /**
   * Sets the process model for the vehicle represented by this entry.
   *
   * @param processModel The new process model for the vehicle.
   */
  public void setProcessModel(@Nonnull VehicleProcessModel processModel) {
    VehicleProcessModel oldProcessModel = this.processModel;
    this.processModel = requireNonNull(processModel, "processModel");

    oldProcessModel.removePropertyChangeListener(this);
    processModel.addPropertyChangeListener(this);

    pcs.firePropertyChange(Attribute.PROCESS_MODEL.name(), oldProcessModel, processModel);
  }

  @Nonnull
  public VehicleCommAdapterFactory getCommAdapterFactory() {
    return commAdapterFactory;
  }

  /**
   * Sets the comm adapter factory for this entry.
   *
   * @param commAdapterFactory The new comm adapter factory.
   */
  public void setCommAdapterFactory(@Nonnull VehicleCommAdapterFactory commAdapterFactory) {
    VehicleCommAdapterFactory oldValue = this.commAdapterFactory;
    this.commAdapterFactory = commAdapterFactory;

    pcs.firePropertyChange(Attribute.COMM_ADAPTER_FACTORY.name(), oldValue, commAdapterFactory);
  }

  /**
   * Returns the comm adapter factory for this entry.
   *
   * @return The comm adapter factory for this entry
   */
  @Nullable
  public VehicleCommAdapter getCommAdapter() {
    return commAdapter;
  }

  /**
   * Sets the comm adapter for this entry.
   *
   * @param commAdapter The new comm adapter.
   */
  public void setCommAdapter(@Nullable VehicleCommAdapter commAdapter) {
    VehicleCommAdapter oldValue = this.commAdapter;
    this.commAdapter = commAdapter;

    pcs.firePropertyChange(Attribute.COMM_ADAPTER.name(), oldValue, commAdapter);
  }

  /**
   * Enum elements used as notification arguments to specify which argument changed.
   */
  public enum Attribute {
    /**
     * Indicates a change of the process model reference.
     */
    PROCESS_MODEL,
    /**
     * Indicates a change of the comm adapter factory reference.
     */
    COMM_ADAPTER_FACTORY,
    /**
     * Indicates a change of the comm adapter reference.
     */
    COMM_ADAPTER
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/package-info.java<|end_filename|>
/**
 * Components needed for controlling physical vehicles and processing information sent by them.
 */
package org.opentcs.drivers.vehicle;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/PointRouter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing;

import java.util.List;
import static java.util.Objects.requireNonNull;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Point;
import org.opentcs.data.order.Route;

/**
 * Computes routes between points.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PointRouter {

  /**
   * A constant for marking the costs for a route as infinite.
   */
  long INFINITE_COSTS = Long.MAX_VALUE;

  /**
   * Returns a list of route steps to travel from a given source point to a given destination point.
   *
   * @param srcPoint The source point.
   * @param destPoint The destination point.
   * @return A list of steps in the order they are to be travelled from the source point to the
   * destination point.
   * The returned list does not include a step for the source point.
   * If source point and destination point are identical, the returned list will be empty.
   * If no route exists, <code>null</code> will be returned.
   */
  List<Route.Step> getRouteSteps(Point srcPoint, Point destPoint);

  /**
   * Returns the costs for travelling the shortest route from one point to another.
   *
   * @param srcPointRef The starting point reference.
   * @param destPointRef The destination point reference.
   * @return The costs for travelling the shortest route from the starting point to the destination
   * point.
   * If no route exists, {@link #INFINITE_COSTS INFINITE_COSTS} will be returned.
   */
  public long getCosts(TCSObjectReference<Point> srcPointRef,
                       TCSObjectReference<Point> destPointRef);

  /**
   * Returns the costs for travelling the shortest route from one point to another.
   *
   * @param srcPoint The starting point.
   * @param destPoint The destination point.
   * @return The costs for travelling the shortest route from the starting point to the destination
   * point.
   * If no route exists, {@link #INFINITE_COSTS INFINITE_COSTS} will be returned.
   */
  default long getCosts(Point srcPoint, Point destPoint) {
    requireNonNull(srcPoint, "srcPoint");
    requireNonNull(destPoint, "destPoint");

    return getCosts(srcPoint.getReference(), destPoint.getReference());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RegistrationName.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

/**
 * Defines the names used for binding the remote services in the RMI registry.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RegistrationName {

  /**
   * The name the {@link RemoteKernelServicePortal} registers itself with a RMI registry.
   */
  String REMOTE_KERNEL_CLIENT_PORTAL = RemoteKernelServicePortal.class.getCanonicalName();
  /**
   * The name the {@link RemotePlantModelService} registers itself with a RMI registry.
   */
  String REMOTE_PLANT_MODEL_SERVICE = RemotePlantModelService.class.getCanonicalName();
  /**
   * The name the {@link RemoteTransportOrderService} registers itself with a RMI registry.
   */
  String REMOTE_TRANSPORT_ORDER_SERVICE = RemoteTransportOrderService.class.getCanonicalName();
  /**
   * The name the {@link RemoteVehicleService} registers itself with a RMI registry.
   */
  String REMOTE_VEHICLE_SERVICE = RemoteVehicleService.class.getCanonicalName();
  /**
   * The name the {@link RemoteNotificationService} registers itself with a RMI registry.
   */
  String REMOTE_NOTIFICATION_SERVICE = RemoteNotificationService.class.getCanonicalName();
  /**
   * The name the {@link RemoteRouterService} registers itself with a RMI registry.
   */
  String REMOTE_ROUTER_SERVICE = RemoteRouterService.class.getCanonicalName();
  /**
   * The name the {@link RemoteDispatcherService} registers itself with a RMI registry.
   */
  String REMOTE_DISPATCHER_SERVICE = RemoteDispatcherService.class.getCanonicalName();
  /**
   * The name the {@link RemoteSchedulerService} registers itself with a RMI registry.
   */
  String REMOTE_SCHEDULER_SERVICE = RemoteSchedulerService.class.getCanonicalName();
  /**
   * The name the {@link RemoteQueryService} registers itself with a RMI registry.
   */
  String REMOTE_QUERY_SERVICE = RemoteQueryService.class.getCanonicalName();
  /**
   * The name the {@link RemotePeripheralService} registers itself with a RMI registry.
   */
  String REMOTE_PERIPHERAL_SERVICE = RemotePeripheralService.class.getCanonicalName();
  /**
   * The name the {@link RemotePeripheralJobService} registers itself with a RMI registry.
   */
  String REMOTE_PERIPHERAL_JOB_SERVICE = RemotePeripheralJobService.class.getCanonicalName();
  /**
   * The name the {@link RemotePeripheralDispatcherService} registers itself with a RMI registry.
   */
  String REMOTE_PERIPHERAL_DISPATCHER_SERVICE
      = RemotePeripheralDispatcherService.class.getCanonicalName();
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/application/toolbar/OpenTCSDragTracker.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.toolbar;

import java.awt.Container;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.event.TransformEdit;
import org.jhotdraw.draw.tool.DefaultDragTracker;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.components.drawing.figures.PathConnection;
import org.opentcs.guing.components.drawing.figures.liner.BezierLinerEdit;

/**
 * Utility to follow the drags made by the user.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSDragTracker
    extends DefaultDragTracker {

  /**
   * Stores the application's current state.
   */
  private final ApplicationState appState;
  /**
   * The affected figures.
   */
  private Set<Figure> transformedFigures;
  /**
   * Indicates whether the user is dragging the mouse or not.
   */
  private boolean isDragging;

  /**
   * Creates a new instance.
   *
   * @param appState Stores the application's current state.
   */
  @Inject
  public OpenTCSDragTracker(ApplicationState appState) {
    this.appState = requireNonNull(appState, "appState");
  }

  @Override
  public void mousePressed(MouseEvent evt) {
    DrawingView view = editor.findView((Container) evt.getSource());
    view.requestFocus();
    anchor = new Point(evt.getX(), evt.getY());
    isWorking = true;
    fireToolStarted(view);
    view = getView();

    if (evt.isShiftDown()) {
      view.toggleSelection(anchorFigure);

      if (!view.isFigureSelected(anchorFigure)) {
        anchorFigure = null;
      }
    }
    else if (!view.isFigureSelected(anchorFigure)) {
      view.clearSelection();
      view.addToSelection(anchorFigure);
    }

    if (!view.getSelectedFigures().isEmpty()) {
      dragRect = null;
      transformedFigures = new HashSet<>();

      for (Figure f : view.getSelectedFigures()) {
        if (f.isTransformable()) {
          transformedFigures.add(f);

          if (dragRect == null) {
            dragRect = f.getBounds();
          }
          else {
            dragRect.add(f.getBounds());
          }
        }
      }

      if (dragRect != null) {
        anchorPoint = view.viewToDrawing(anchor);
        previousPoint = anchorPoint;
        anchorOrigin = new Point2D.Double(dragRect.x, dragRect.y);
        previousOrigin = anchorOrigin;
      }
    }
  }

  @Override
  public void mouseDragged(MouseEvent evt) {
    DrawingView drawingView = getView();

    switch (appState.getOperationMode()) {
      case MODELLING:
        if (!transformedFigures.isEmpty()) {
          if (!isDragging) {
            isDragging = true;
            updateCursor(editor.findView((Container) evt.getSource()), new Point(evt.getX(), evt.getY()));
          }

          Point2D.Double currentPoint = drawingView.viewToDrawing(new Point(evt.getX(), evt.getY()));
          double offsetX = currentPoint.x - previousPoint.x;
          double offsetY = currentPoint.y - previousPoint.y;
          dragRect.x += offsetX;
          dragRect.y += offsetY;
          Rectangle2D.Double constrainedRect = (Rectangle2D.Double) dragRect.clone();

          if (drawingView.getConstrainer() != null) {
            drawingView.getConstrainer().constrainRectangle(constrainedRect);
          }

          AffineTransform tx = new AffineTransform();
          tx.translate(
              constrainedRect.x - previousOrigin.x,
              constrainedRect.y - previousOrigin.y);

          for (Figure f : transformedFigures) {
            f.willChange();
            f.transform(tx);
            f.changed();
          }

          previousPoint = currentPoint;
          previousOrigin = new Point2D.Double(constrainedRect.x, constrainedRect.y);
        }

        break;

      case OPERATING:
      default:
    }
  }

  @Override // DefaultDragTracker
  public void mouseReleased(MouseEvent evt) {
    isWorking = false;
    DrawingView view = getView();

    if (transformedFigures != null && !transformedFigures.isEmpty()) {
      isDragging = false;
      int x = evt.getX();
      int y = evt.getY();
      updateCursor(editor.findView((Container) evt.getSource()), new Point(x, y));
      Point2D.Double newPoint = view.viewToDrawing(new Point(x, y));
      Figure dropTarget = getDrawing().findFigureExcept(newPoint, transformedFigures);

      if (dropTarget != null) {
        boolean snapBack = dropTarget.handleDrop(newPoint, transformedFigures, view);

        if (snapBack) {
          AffineTransform tx = new AffineTransform();
          tx.translate(
              anchorOrigin.x - previousOrigin.x,
              anchorOrigin.y - previousOrigin.y);

          for (Figure f : transformedFigures) {
            f.willChange();
            f.transform(tx);
            f.changed();
          }

          Rectangle r = new Rectangle(anchor.x, anchor.y, 0, 0);
          r.add(evt.getX(), evt.getY());
          maybeFireBoundsInvalidated(r);
          fireToolDone();

          return;
        }
      }

      AffineTransform tx = new AffineTransform();
      tx.translate(
          -anchorOrigin.x + previousOrigin.x,
          -anchorOrigin.y + previousOrigin.y);

      if (!tx.isIdentity()) {
        getDrawing().fireUndoableEditHappened(
            new TransformEdit(transformedFigures, tx));
      }

      // On changes on a path
      Object[] aFigures = transformedFigures.toArray();

      if (aFigures[0] instanceof PathConnection) {
        getDrawing().fireUndoableEditHappened(new BezierLinerEdit((PathConnection) aFigures[0]));
      }
    }

    Rectangle r = new Rectangle(anchor.x, anchor.y, 0, 0);
    r.add(evt.getX(), evt.getY());
    maybeFireBoundsInvalidated(r);
    transformedFigures = null;
    fireToolDone();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemotePeripheralServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;

/**
 * The default implementation of the vehicle service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemotePeripheralServiceProxy
    extends RemoteTCSObjectServiceProxy<RemotePeripheralService>
    implements PeripheralService {

  @Override
  public void attachCommAdapter(TCSResourceReference<Location> ref,
                                PeripheralCommAdapterDescription description)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().attachCommAdapter(getClientId(), ref, description);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void disableCommAdapter(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().disableCommAdapter(getClientId(), ref);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void enableCommAdapter(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().enableCommAdapter(getClientId(), ref);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public PeripheralAttachmentInformation fetchAttachmentInformation(
      TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchAttachmentInformation(getClientId(), ref);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public PeripheralProcessModel fetchProcessModel(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchProcessModel(getClientId(), ref);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void sendCommAdapterCommand(TCSResourceReference<Location> ref,
                                     PeripheralAdapterCommand command)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().sendCommAdapterCommand(getClientId(), ref, command);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/annotations/package-info.java<|end_filename|>
/**
 * Useful annotations.
 */
package org.opentcs.util.annotations;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/LinerTypePropertyCellRenderer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Component;
import javax.swing.JLabel;
import javax.swing.JTable;
import org.opentcs.guing.components.properties.type.LinerTypeProperty;
import org.opentcs.guing.model.elements.PathModel.Type;

/**
 * A cell renderer for a {@link LinerTypeProperty}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LinerTypePropertyCellRenderer
    extends StandardPropertyCellRenderer {

  public LinerTypePropertyCellRenderer() {
    super();
  }

  @Override
  public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected,
                                                                hasFocus, row, column);

    if (value instanceof LinerTypeProperty
        && ((LinerTypeProperty) value).getValue() instanceof Type) {
      LinerTypeProperty property = (LinerTypeProperty) value;
      Type type = (Type) property.getValue();
      label.setText(type.getDescription());
    }

    decorate(table, row, column, label, value);

    return this;
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/xmlbinding/DriveOrderEntry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.xmlbinding;

import static java.util.Objects.requireNonNull;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

/**
 * Stores a drive order definition for XML marshalling/unmarshalling.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
@XmlType(propOrder = {"locationName", "vehicleOperation"})
public class DriveOrderEntry {

  /**
   * The name of this drive order's location.
   */
  private String locationName;
  /**
   * The operation to be executed at the location.
   */
  private String vehicleOperation;

  /**
   * Creates a new instance.
   *
   * @param locationName The reference to the drive order's location.
   * @param vehicleOperation The available operation type at the location.
   */
  public DriveOrderEntry(String locationName, String vehicleOperation) {
    this.locationName = requireNonNull(locationName, "locationName");
    this.vehicleOperation = requireNonNull(vehicleOperation, "vehicleOperation");
  }

  /**
   * Creates a new instance.
   */
  public DriveOrderEntry() {
  }

  /**
   * Returns a reference to the location.
   *
   * @return The reference to the location.
   */
  @XmlAttribute(name = "locationName", required = true)
  public String getLocationName() {
    return locationName;
  }

  /**
   * Sets the drive order location.
   *
   * @param locationName The new location.
   */
  public void setLocationName(String locationName) {
    this.locationName = locationName;
  }

  /**
   * Returns this drive order's operation.
   *
   * @return The drive order's operation.
   */
  @XmlAttribute(name = "vehicleOperation", required = true)
  public String getVehicleOperation() {
    return this.vehicleOperation;
  }

  /**
   * Sets the drive order vehicle operation.
   *
   * @param vehicleOperation The new operation
   */
  public void setVehicleOperation(String vehicleOperation) {
    this.vehicleOperation = vehicleOperation;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/SharedKernelServicePortal.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

/**
 * Provides access to a shared {@link KernelServicePortal} instance.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface SharedKernelServicePortal
    extends AutoCloseable {

  @Override
  public void close();

  /**
   * Indicates whether this instance is closed/unregistered from the shared portal pool.
   *
   * @return {@code true} if, and only if, this instance is closed.
   */
  boolean isClosed();

  /**
   * Returns the {@link KernelServicePortal} instance being shared.
   *
   * @return The portal instance being shared.
   * @throws IllegalStateException If this instance is closed.
   */
  KernelServicePortal getPortal()
      throws IllegalStateException;
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/LocationTypeTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "locationNamePrefix", "allowedOperations", "properties"})
public class LocationTypeTO
    extends PlantModelElementTO {

  private String locationNamePrefix;
  private List<AllowedOperationTO> allowedOperations = new ArrayList<>();

  @XmlAttribute
  public String getLocationNamePrefix() {
    return locationNamePrefix;
  }

  public LocationTypeTO setLocationNamePrefix(String locationNamePrefix) {
    this.locationNamePrefix = locationNamePrefix;
    return this;
  }

  @XmlElement(name = "allowedOperation")
  public List<AllowedOperationTO> getAllowedOperations() {
    return allowedOperations;
  }

  public LocationTypeTO setAllowedOperations(@Nonnull List<AllowedOperationTO> allowedOperations) {
    requireNonNull(allowedOperations, "allowedOperations");
    this.allowedOperations = allowedOperations;
    return this;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/PlantModelExporter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.io.IOException;
import javax.annotation.Nonnull;
import org.opentcs.access.to.model.PlantModelCreationTO;

/**
 * Implementations provide a way to export plant model data, for instance to write it to a file in a
 * third-party format or to a database.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PlantModelExporter {

  /**
   * Exports the given plant model data.
   *
   * @param model The plant model data to be exported.
   * @throws IOException If there was a problem exporting plant model data.
   */
  void exportPlantModel(@Nonnull PlantModelCreationTO model)
      throws IOException;

  /**
   * Returns a (localized) short textual description of this importer.
   *
   * @return A (localized) short textual description of this importer.
   */
  @Nonnull
  String getDescription();
}


<|start_filename|>openTCS-Common/src/test/java/org/opentcs/util/ColorsTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.awt.Color;
import org.junit.*;
import static org.junit.Assert.*;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ColorsTest {

  @Test
  public void testEncodeToHexRGB() {
    assertEquals("#000000", Colors.encodeToHexRGB(new Color(0, 0, 0)));
    assertEquals("#FFFFFF", Colors.encodeToHexRGB(new Color(255, 255, 255)));
    assertEquals("#FF0000", Colors.encodeToHexRGB(new Color(255, 0, 0)));
    assertEquals("#00FF00", Colors.encodeToHexRGB(new Color(0, 255, 0)));
    assertEquals("#0000FF", Colors.encodeToHexRGB(new Color(0, 0, 255)));
    assertEquals("#000001", Colors.encodeToHexRGB(new Color(0, 0, 1)));
    assertEquals("#000100", Colors.encodeToHexRGB(new Color(0, 1, 0)));
    assertEquals("#010000", Colors.encodeToHexRGB(new Color(1, 0, 0)));
  }

  @Test
  public void testDecodeFromHexRGB() {
    Color color;

    color = Colors.decodeFromHexRGB("#000000");
    assertEquals(0, color.getRed());
    assertEquals(0, color.getGreen());
    assertEquals(0, color.getBlue());

    color = Colors.decodeFromHexRGB("#FFFFFF");
    assertEquals(255, color.getRed());
    assertEquals(255, color.getGreen());
    assertEquals(255, color.getBlue());

    color = Colors.decodeFromHexRGB("#010000");
    assertEquals(1, color.getRed());
    assertEquals(0, color.getGreen());
    assertEquals(0, color.getBlue());

    color = Colors.decodeFromHexRGB("#000100");
    assertEquals(0, color.getRed());
    assertEquals(1, color.getGreen());
    assertEquals(0, color.getBlue());

    color = Colors.decodeFromHexRGB("#000001");
    assertEquals(0, color.getRed());
    assertEquals(0, color.getGreen());
    assertEquals(1, color.getBlue());
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/scheduling/ReservationPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.scheduling;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Queue;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.data.model.TCSResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ReservationPool {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ReservationPool.class);
  /**
   * All claims.
   */
  private final Map<Scheduler.Client, Queue<Set<TCSResource<?>>>> claimsByClient
      = new HashMap<>();
  /**
   * <code>ReservationEntry</code> instances for each <code>TCSResource</code>.
   */
  private final Map<TCSResource<?>, ReservationEntry> reservations = new HashMap<>();

  /**
   * Creates a new instance.
   */
  @Inject
  public ReservationPool() {
  }

  /**
   * Returns a reservation entry for the given resource.
   *
   * @param resource The resource for which to return the reservation entry.
   * @return The reservation entry for the given resource.
   */
  @Nonnull
  public ReservationEntry getReservationEntry(TCSResource<?> resource) {
    requireNonNull(resource, "resource");

    ReservationEntry entry = reservations.get(resource);
    if (entry == null) {
      entry = new ReservationEntry(resource);
      reservations.put(resource, entry);
    }
    return entry;
  }

  /**
   * Returns the sequence of resource sets claimed by the given client.
   *
   * @param client The client.
   * @return The sequence of resource sets claimed by the given client.
   */
  @Nonnull
  public List<Set<TCSResource<?>>> getClaim(@Nonnull Scheduler.Client client) {
    requireNonNull(client, "client");

    return claimsByClient.getOrDefault(client, new LinkedList<>()).stream()
        .map(resourceSet -> Set.copyOf(resourceSet))
        .collect(Collectors.toList());
  }

  /**
   * Sets the sequence of claimed resource sets for the given client.
   *
   * @param client The client.
   * @param resources The sequence of claimed resources.
   */
  public void setClaim(@Nonnull Scheduler.Client client,
                       @Nonnull List<Set<TCSResource<?>>> resources) {
    requireNonNull(client, "client");
    requireNonNull(resources, "resources");

    claimsByClient.put(client, new LinkedList<>(resources));
  }

  /**
   * Removes the given resource set from the head of the sequence of claimed resource sets for the
   * given client.
   *
   * @param client The client.
   * @param resources The resource set to be removed from the head of the client's claim sequence.
   * @throws IllegalArgumentException If the given resource set is not the head of the client's
   * claim sequence.
   */
  public void unclaim(@Nonnull Scheduler.Client client, @Nonnull Set<TCSResource<?>> resources)
      throws IllegalArgumentException {
    requireNonNull(client, "client");
    requireNonNull(resources, "resources");

    if (!claimsByClient.containsKey(client) || claimsByClient.get(client).isEmpty()) {
      return;
    }

    if (!isNextInClaim(client, resources)) {
      throw new IllegalArgumentException(
          String.format("Resources to unclaim and head of claimed resource don't match: %s != %s",
                        resources,
                        claimsByClient.get(client).peek())
      );
    }

    claimsByClient.get(client).remove();
  }

  /**
   * Checks whether the given resource set is at the head of the given client's claim sequence.
   *
   * @param client The client.
   * @param resources The resources to be checked.
   * @return <code>true</code> if, and only if, the given resource set is at the head of the given
   * client's claim sequence.
   */
  public boolean isNextInClaim(@Nonnull Scheduler.Client client,
                               @Nonnull Set<TCSResource<?>> resources) {
    requireNonNull(client, "client");
    requireNonNull(resources, "resources");

    if (!claimsByClient.containsKey(client) || claimsByClient.get(client).isEmpty()) {
      return false;
    }

    if (!Objects.equals(resources, claimsByClient.get(client).peek())) {
      return false;
    }

    return true;
  }

  /**
   * Returns all resources allocated by the given client.
   *
   * @param client The client for which to return all allocated resources.
   * @return All resources allocated by the given client.
   */
  @Nonnull
  public Set<TCSResource<?>> allocatedResources(@Nonnull Scheduler.Client client) {
    requireNonNull(client, "client");

    return reservations.entrySet().stream()
        .filter(entry -> entry.getValue().isAllocatedBy(client))
        .map(entry -> entry.getKey())
        .collect(Collectors.toSet());
  }

  /**
   * Checks if all resources in the given set of resources are be available for the given client.
   *
   * @param resources The set of resources to be checked.
   * @param client The client for which to check.
   * @return <code>true</code> if, and only if, all resources in the given set
   * are available for the given client.
   */
  public boolean resourcesAvailableForUser(@Nonnull Set<TCSResource<?>> resources,
                                           @Nonnull Scheduler.Client client) {
    requireNonNull(resources, "resources");
    requireNonNull(client, "client");

    for (TCSResource<?> curResource : resources) {
      // Check if the resource is available.
      ReservationEntry entry = getReservationEntry(curResource);
      if (!entry.isFree() && !entry.isAllocatedBy(client)) {
        LOG.debug("{}: Resource unavailable: {}", client.getId(), entry.getResource());
        return false;
      }
    }
    return true;
  }

  public void free(@Nonnull Scheduler.Client client, @Nonnull Set<TCSResource<?>> resources) {
    requireNonNull(client, "client");
    requireNonNull(resources, "resources");

    LOG.debug("{}: Releasing resources: {}", client.getId(), resources);
    for (TCSResource<?> curResource : getFreeableResources(resources, client)) {
      getReservationEntry(curResource).free();
    }
  }

  public void freeAll(@Nonnull Scheduler.Client client) {
    requireNonNull(client, "client");

    reservations.values().stream()
        .filter(reservationEntry -> reservationEntry.isAllocatedBy(client))
        .forEach(reservationEntry -> reservationEntry.freeCompletely());
  }

  @Nonnull
  public Map<String, Set<TCSResource<?>>> getAllocations() {
    final Map<String, Set<TCSResource<?>>> result = new HashMap<>();
    for (Map.Entry<TCSResource<?>, ReservationEntry> curEntry : reservations.entrySet()) {
      final TCSResource<?> curResource = curEntry.getKey();
      final Scheduler.Client curUser = curEntry.getValue().getClient();
      if (curUser != null) {
        Set<TCSResource<?>> userResources = result.get(curUser.getId());
        if (userResources == null) {
          userResources = new HashSet<>();
        }
        userResources.add(curResource);
        result.put(curUser.getId(), userResources);
      }
    }
    return result;
  }

  public void clear() {
    claimsByClient.clear();
    reservations.clear();
  }

  /**
   * Returns a set of resources that is a subset of the given set of resources and is reserved/could
   * be released by the given client.
   *
   * @param resources The set of resources to be filtered for resources that could be released.
   * @param client The client that should be able to release the returned resources.
   * @return A set of resources that is a subset of the given set of resources and is reserved/could
   * be released by the given client.
   */
  @Nonnull
  private Set<TCSResource<?>> getFreeableResources(@Nonnull Set<TCSResource<?>> resources,
                                                   @Nonnull Scheduler.Client client) {
    // Make sure we're freeing only resources that are allocated by us.
    final Set<TCSResource<?>> freeableResources = new HashSet<>();
    for (TCSResource<?> curRes : resources) {
      ReservationEntry entry = getReservationEntry(curRes);
      if (!entry.isAllocatedBy(client)) {
        LOG.warn("{}: Freed resource not reserved: {}, entry: {}", client.getId(), curRes, entry);
      }
      else {
        freeableResources.add(curRes);
      }
    }
    return freeableResources;
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/edit/CopyAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.action.edit;

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import static javax.swing.Action.ACCELERATOR_KEY;
import static javax.swing.Action.LARGE_ICON_KEY;
import static javax.swing.Action.SMALL_ICON;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import org.jhotdraw.app.action.edit.AbstractSelectionAction;
import org.opentcs.guing.components.EditableComponent;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.MENU_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Copies the selected region and place its contents into the system clipboard.
 * This action acts on the last EditableComponent / {@code JTextComponent}
 * which had the focus when the {@code ActionEvent} was generated.
 * This action is called when the user selects the "Copy" item in the Edit menu.
 * The menu item is automatically created by the application.
 *
 * @author <NAME>
 */
public class CopyAction
    extends AbstractSelectionAction {

  public final static String ID = "edit.copy";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);

  /**
   * Creates a new instance which acts on the currently focused component.
   */
  public CopyAction() {
    this(null);
  }

  /**
   * Creates a new instance which acts on the specified component.
   *
   * @param target The target of the action. Specify null for the currently
   * focused component.
   */
  public CopyAction(JComponent target) {
    super(target);

    putValue(NAME, BUNDLE.getString("copyAction.name"));
    putValue(SHORT_DESCRIPTION, BUNDLE.getString("copyAction.shortDescription"));
    putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl C"));

    ImageIcon icon = ImageDirectory.getImageIcon("/menu/edit-copy-4.png");
    putValue(SMALL_ICON, icon);
    putValue(LARGE_ICON_KEY, icon);
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    Component cFocusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();

    if (cFocusOwner instanceof JComponent) {
      if (cFocusOwner.isEnabled()) {
        // Cut all selected UserObjects from the tree
        if (cFocusOwner instanceof EditableComponent) {
          ((EditableComponent) cFocusOwner).copySelectedItems();
        }
      }
    }

    // "Old" version with JHotDraw clipboard
//    JComponent cTarget = target;
//
//    if (cTarget == null && (cFocusOwner instanceof JComponent)) {
//      cTarget = (JComponent) cFocusOwner;
//    }
//    // Note: copying is allowed for disabled components
//    if (cTarget != null && cTarget.getTransferHandler() != null) {
//      cTarget.getTransferHandler().exportToClipboard(cTarget, ClipboardUtil.getClipboard(), TransferHandler.COPY);
//    }
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/EditableComboBoxListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.function.Function;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/**
 * A validator for the input of the textfield.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EditableComboBoxListener<E>
    implements DocumentListener {

  private final JTextField textField;
  private final List<ValidationListener> validationListeners;
  private final Set<E> content;

  /**
   * Returns the string representation for the combo box's selected item.
   */
  private final Function<E, String> representer;

  /**
   * Creates an instance.
   *
   * @param content the elements of the comboBox' dropdownlist.
   * @param validationListeners the listeners to be notified about the validity of the user input.
   * @param textField the textfield with the input to be validated.
   * @param representer Returns the string representation for the combo box's selected item.
   */
  public EditableComboBoxListener(Set<E> content,
                                  List<ValidationListener> validationListeners,
                                  JTextField textField,
                                  Function<E, String> representer) {

    this.content = requireNonNull(content, "content");
    this.validationListeners = requireNonNull(validationListeners, "validationListeners");
    this.textField = requireNonNull(textField, "textField");
    this.representer = requireNonNull(representer, "representer");

  }

  @Override
  public void insertUpdate(DocumentEvent e) {
    validate();
  }

  @Override
  public void removeUpdate(DocumentEvent e) {
    validate();
  }

  @Override
  public void changedUpdate(DocumentEvent e) {
    validate();
  }

  private void notifyValidationListeners(boolean isValid) {
    for (ValidationListener valListener : validationListeners) {
      valListener.validityChanged(new ValidationEvent(this, isValid));
    }
  }

  private void validate() {
    if (textField.getText().equals("")) {
      notifyValidationListeners(true);
      return;
    }

    for (E element : content) {
      if (representer.apply(element).equals(textField.getText())) {
        notifyValidationListeners(true);
        return;
      }
    }
    notifyValidationListeners(false);
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayerEditorEventHandler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.components.drawing.figures.FigureConstants;
import org.opentcs.guing.event.DrawingEditorEvent;
import org.opentcs.guing.event.DrawingEditorListener;
import org.opentcs.guing.model.DrawnModelComponent;
import org.opentcs.guing.model.ModelComponent;

/**
 * Handles drawing editor events that the layer editor needs to know about.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerEditorEventHandler
    implements DrawingEditorListener {

  /**
   * The layer editor.
   */
  private final LayerEditorModeling layerEditor;

  @Inject
  public LayerEditorEventHandler(LayerEditorModeling layerEditor) {
    this.layerEditor = requireNonNull(layerEditor, "layerEditor");
  }

  @Override
  public void figureAdded(DrawingEditorEvent e) {
    Figure figure = e.getFigure();
    ModelComponent model = figure.get(FigureConstants.MODEL);
    if (model instanceof DrawnModelComponent) {
      layerEditor.add((DrawnModelComponent) model);
    }
  }

  @Override
  public void figureRemoved(DrawingEditorEvent e) {
    Figure figure = e.getFigure();
    ModelComponent model = figure.get(FigureConstants.MODEL);
    if (model instanceof DrawnModelComponent) {
      layerEditor.remove((DrawnModelComponent) model);
    }
  }

  @Override
  public void figureSelected(DrawingEditorEvent e) {
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/LocationActionPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Vector;
import java.util.stream.Collectors;
import javax.swing.DefaultComboBoxModel;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.guing.components.dialogs.DialogContent;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * A UI to select a point or location as a destination for a vehicle.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class LocationActionPanel
    extends DialogContent {

  /**
   * Available locations.
   */
  protected List<LocationModel> fLocations;
  /**
   * Available actions.
   */
  protected List<String> fActions;

  /**
   * Creates new instance.
   *
   * @param locations The location models.
   */
  public LocationActionPanel(List<LocationModel> locations) {
    this.fLocations = requireNonNull(locations, "locations");

    initComponents();

    setDialogTitle(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.VEHICLEPOPUP_PATH)
        .getString("locationActionPanel.title"));

    Collections.sort(fLocations, getComparator());

    List<String> names = fLocations.stream()
        .map(location -> location.getName())
        .collect(Collectors.toList());

    locationsComboBox.setModel(new DefaultComboBoxModel<>(new Vector<>(names)));

    updateActions();
  }

  /**
   * Returns a Comparator to sort model components by their name.
   *
   * @return The Comparator
   */
  protected final Comparator<ModelComponent> getComparator() {
    return (ModelComponent item1, ModelComponent item2) -> {
      String s1 = item1.getName();
      String s2 = item2.getName();
      s1 = s1.toLowerCase();
      s2 = s2.toLowerCase();

      return s1.compareTo(s2);
    };
  }

  /**
   * Returns the selected location.
   *
   * @return the selected location or null.
   */
  public LocationModel getSelectedLocation() {
    int index = locationsComboBox.getSelectedIndex();

    if (index == -1) {
      return null;
    }

    return fLocations.get(index);
  }

  public String getSelectedAction() {
    int index = actionsComboBox.getSelectedIndex();

    if (index == -1) {
      return null;
    }

    return fActions.get(index);
  }

  private void updateActions() {
    LocationModel selectedLocation = getSelectedLocation();
    LocationTypeModel locationType = selectedLocation.getLocationType();
    List<String> actions = locationType.getPropertyAllowedOperations().getItems();
    Collections.sort(actions);
    fActions = new ArrayList<>();
    fActions.add(DriveOrder.Destination.OP_NOP);
    fActions.addAll(actions);
    actionsComboBox.setModel(new DefaultComboBoxModel<>(new Vector<>(fActions)));
  }

  @Override
  public void update() {
  }

  @Override
  public void initFields() {
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    locationsLabel = new javax.swing.JLabel();
    locationsComboBox = new javax.swing.JComboBox<>();
    actionsLabel = new javax.swing.JLabel();
    actionsComboBox = new javax.swing.JComboBox<>();

    setPreferredSize(new java.awt.Dimension(150, 40));
    setLayout(new java.awt.GridBagLayout());

    locationsLabel.setFont(locationsLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/operating/dialogs/vehiclePopup"); // NOI18N
    locationsLabel.setText(bundle.getString("locationActionPanel.label_location.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
    add(locationsLabel, gridBagConstraints);

    locationsComboBox.setFont(locationsComboBox.getFont());
    locationsComboBox.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        locationsComboBoxItemStateChanged(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 0.5;
    add(locationsComboBox, gridBagConstraints);

    actionsLabel.setFont(actionsLabel.getFont());
    actionsLabel.setText(bundle.getString("locationActionPanel.label_action.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
    gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
    add(actionsLabel, gridBagConstraints);

    actionsComboBox.setFont(actionsComboBox.getFont());
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    add(actionsComboBox, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents

  private void locationsComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_locationsComboBoxItemStateChanged
    updateActions();
  }//GEN-LAST:event_locationsComboBoxItemStateChanged

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<String> actionsComboBox;
  private javax.swing.JLabel actionsLabel;
  private javax.swing.JComboBox<String> locationsComboBox;
  private javax.swing.JLabel locationsLabel;
  // End of variables declaration//GEN-END:variables
}


<|start_filename|>openTCS-PlantOverview-Base/src/test/java/org/opentcs/guing/components/properties/type/LengthPropertyTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;
import org.opentcs.guing.components.properties.type.LengthProperty.Unit;
import org.opentcs.guing.model.AbstractModelComponent;

/**
 * A test for a length property.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class LengthPropertyTest {

  private LengthProperty property;

  @ParameterizedTest
  @ValueSource(strings = {"mm", "cm", "m", "km"})
  public void testValidUnits(String unit) {
    property = new LengthProperty(new DummyComponent());
    assertTrue(property.isPossibleUnit(unit));
  }

  @ParameterizedTest
  @MethodSource("paramsFactory")
  public void testPropertyConversion(Unit unit, Object result) {
    property = new LengthProperty(new DummyComponent(), 10, Unit.CM);
    property.convertTo(unit);
    assertEquals(result, property.getValue());
    assertEquals(unit, property.getUnit());
  }

  @Test
  public void testPropertyRange() {
    property = new LengthProperty(new DummyComponent());
    assertEquals(0, property.getValidRange().getMin(), 0);
    assertEquals(Double.MAX_VALUE, property.getValidRange().getMax(), 0);
  }

  public static Object[][] paramsFactory() {
    return new Object[][] {{Unit.MM, 100.0},
                           {Unit.CM, 10.0},
                           {Unit.M, 0.1},
                           {Unit.KM, 0.0001}};
  }

  private class DummyComponent
      extends AbstractModelComponent {
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/layer/LayerGroupsPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.awt.BorderLayout;
import java.util.Arrays;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.TableRowSorter;
import org.opentcs.guing.persistence.ModelManager;

/**
 * A panel to display and edit layer groups.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerGroupsPanel
    extends JPanel {

  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer manager.
   */
  private final LayerGroupManager layerGroupManager;
  /**
   * The layer editor.
   */
  private final LayerGroupEditor layerGroupEditor;
  /**
   * The table to display available layers.
   */
  private JTable table;
  /**
   * The table model.
   */
  private LayerGroupsTableModel tableModel;

  @Inject
  public LayerGroupsPanel(ModelManager modelManager,
                          LayerGroupManager layerGroupManager,
                          LayerGroupEditor layerGroupEditor) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerGroupManager = requireNonNull(layerGroupManager, "layerGroupManager");
    this.layerGroupEditor = requireNonNull(layerGroupEditor, "layerGroupEditor");

    initComponents();
  }

  private void initComponents() {
    setLayout(new BorderLayout());

    tableModel = new LayerGroupsTableModel(modelManager, layerGroupEditor);
    layerGroupManager.addLayerGroupChangeListener(tableModel);
    table = new JTable(tableModel);
    initTable();

    add(new JScrollPane(table), BorderLayout.CENTER);
  }

  private void initTable() {
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    TableRowSorter<LayerGroupsTableModel> sorter = new TableRowSorter<>(tableModel);
    // Sort the table by the layer ordinals...
    sorter.setSortKeys(Arrays.asList(
        new RowSorter.SortKey(LayerGroupsTableModel.COLUMN_ID, SortOrder.DESCENDING)
    ));
    // ...but prevent manual sorting.
    for (int i = 0; i < table.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    table.setRowSorter(sorter);

    // Hide the column that shows the layer group IDs.
    table.removeColumn(table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayerGroupsTableModel.COLUMN_ID)));
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/FilteredRowSorter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.swing.RowFilter;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

/**
 * A table model sorter that implements some convinience methods for easier filtering.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <T> The table model class
 */
public class FilteredRowSorter<T extends TableModel>
    extends TableRowSorter<T> {

  /**
   * Keeps all the active filters.
   */
  private final List<RowFilter<Object, Object>> filters = new LinkedList<>();

  public FilteredRowSorter(T model) {
    super(model);
  }

  /**
   * Add a new filter to the sorter.
   *
   * @param filter Filter to add.
   */
  public void addRowFilter(RowFilter<Object, Object> filter) {
    requireNonNull(filter, "filter");
    filters.add(filter);
    setRowFilter(RowFilter.andFilter(filters));
  }

  /**
   * Removes a filter from the sorter.
   *
   * @param filter Filter to remove.
   */
  public void removeRowFilter(RowFilter<Object, Object> filter) {
    requireNonNull(filter, "filter");
    filters.remove(filter);
    setRowFilter(RowFilter.andFilter(filters));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/VehicleCommAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.services.VehicleService;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
import org.opentcs.util.ExplainedBoolean;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * This interface declares the methods that a driver communicating with and
 * controlling a physical vehicle must implement.
 * <p>
 * A communication adapter is basically a driver that converts high-level
 * commands sent by openTCS to a form that the controlled vehicles understand.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleCommAdapter
    extends Lifecycle {

  /**
   * Enables this comm adapter, i.e. turns it on.
   */
  void enable();

  /**
   * Disables this comm adapter, i.e. turns it off.
   */
  void disable();

  /**
   * Checks whether this communication adapter is enabled.
   *
   * @return <code>true</code> if, and only if, this communication adapter is
   * enabled.
   */
  boolean isEnabled();

  /**
   * Returns an observable model of the vehicle's and its comm adapter's attributes.
   *
   * @return An observable model of the vehicle's and its comm adapter's attributes.
   */
  @Nonnull
  VehicleProcessModel getProcessModel();

  /**
   * Returns a transferable/serializable model of the vehicle's and its comm adapter's attributes.
   *
   * @return A transferable/serializable model of the vehicle's and its comm adapter's attributes.
   */
  @Nonnull
  VehicleProcessModelTO createTransferableProcessModel();

  /**
   * Indicates how many commands this comm adapter accepts.
   * <p>
   * This capacity considers both the {@link #getCommandQueue() command queue} and the
   * {@link #getSentQueue() sent queue}. This means that the number of elements in both queues
   * combined must not exceed this number.
   * </p>
   *
   * @return The number of commands this comm adapter accepts.
   */
  int getCommandQueueCapacity();

  /**
   * Returns this adapter's command queue.
   * <p>
   * This queue contains {@link MovementCommand}s that the comm adapter received from the
   * {@link VehicleController} it's associated with. When a command is sent to the vehicle, the
   * command is removed from this queue and added to the {@link #getSentQueue() sent queue}.
   * </p>
   *
   * @return This adapter's command queue.
   * @see #getCommandQueueCapacity()
   */
  @Nonnull
  Queue<MovementCommand> getCommandQueue();

  /**
   * Checks whether this comm adapter can accept the next (i.e. one more)
   * {@link MovementCommand command}.
   *
   * @return {@code true}, if this adapter can accept another command, otherwise {@code false}.
   */
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default boolean canAcceptNextCommand() {
    return (getCommandQueue().size() + getSentQueue().size()) < getCommandQueueCapacity();
  }

  /**
   * Returns the capacity of this adapter's {@link #getSentQueue() <em>sent queue</em>}.
   *
   * @return The capacity of this adapter's <em>sent queue</em>.
   */
  int getSentQueueCapacity();

  /**
   * Returns a queue containing the commands that this adapter has sent to the vehicle already but
   * which have not yet been processed by it.
   *
   * @return A queue containing the commands that this adapter has sent to the vehicle already but
   * which have not yet been processed by it.
   * @see #getSentQueueCapacity()
   * @see #getCommandQueueCapacity()
   */
  @Nonnull
  Queue<MovementCommand> getSentQueue();

  /**
   * Returns the string the comm adapter recognizes as a recharge operation.
   *
   * @return The string the comm adapter recognizes as a recharge operation.
   */
  String getRechargeOperation();

  /**
   * Appends a command to this communication adapter's command queue.
   * The return value of this method indicates whether the command was really
   * added to the queue. The primary reason for a commmand not being added to
   * the queue is that it would exceed its capacity.
   *
   * @param newCommand The command to be added to this adapter's command queue.
   * @return <code>true</code> if, and only if, the new command was added to
   * this adapter's command queue.
   */
  boolean enqueueCommand(@Nonnull MovementCommand newCommand);

  /**
   * Clears this communication adapter's command queue.
   * All commands in the queue that have not been sent to this adapter's
   * vehicle, yet, will be removed from the command queue. Any operation the
   * vehicle might currently be executing will still be completed, though.
   */
  void clearCommandQueue();

  /**
   * Checks if the vehicle would be able to process the given transport order, taking into account
   * its current state.
   *
   * @param order The transport order to be checked.
   * @return An <code>ExplainedBoolean</code> indicating whether the vehicle would be able to
   * process the given order.
   */
  @Nonnull
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default ExplainedBoolean canProcess(@Nonnull TransportOrder order) {
    return canProcess(
        order.getFutureDriveOrders().stream()
            .map(driveOrder -> driveOrder.getDestination().getOperation())
            .collect(Collectors.toList())
    );
  }

  /**
   * Checks if the vehicle would be able to process the given sequence of operations, taking into
   * account its current state.
   *
   * @param operations A sequence of operations that might have to be processed as part of a
   * transport order.
   * @return An <code>ExplainedBoolean</code> indicating whether the vehicle would be able to
   * process every single operation in the list (in the given order).
   * @deprecated Use {@link #canProcess(org.opentcs.data.order.TransportOrder)} instead.
   */
  @Nonnull
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default ExplainedBoolean canProcess(@Nonnull List<String> operations) {
    return new ExplainedBoolean(false, "VehicleCommAdapter default implementation");
  }

  /**
   * Processes a generic message to the communication adapter.
   * This method provides a generic one-way communication channel to the comm adapter. The message
   * can be anything, including <code>null</code>, and since
   * {@link VehicleService#sendCommAdapterMessage(org.opentcs.data.TCSObjectReference, java.lang.Object)}
   * provides a way to send a message from outside the kernel, it can basically originate from any
   * source. The message thus does not necessarily have to be meaningful to the concrete comm
   * adapter implementation at all.
   * <p>
   * <em>
   * Implementation notes:
   * Meaningless messages should simply be ignored and not result in exceptions being thrown.
   * If a comm adapter implementation does not support processing messages, it should simply provide
   * an empty implementation.
   * A call to this method should return quickly, i.e. this method should not execute long
   * computations directly but start them in a separate thread.
   * </em></p>
   *
   * @param message The message to be processed.
   */
  void processMessage(@Nullable Object message);

  /**
   * Executes the given {@link AdapterCommand}.
   *
   * @param command The command to execute.
   */
  void execute(@Nonnull AdapterCommand command);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/Ruler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EventObject;
import static java.util.Objects.requireNonNull;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import org.jhotdraw.draw.DrawingView;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.drawing.course.OriginChangeListener;

/**
 * A ruler.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class Ruler
    extends JComponent
    implements PropertyChangeListener,
               OriginChangeListener {

  /**
   * Size of the rulers (height of the horizontal ruler, width of the vertical).
   */
  private static final int SIZE = 25;
  /**
   * The standard translation of the drawing view. Not sure though why
   * it is -12.
   */
  private static final int STANDARD_TRANSLATION = -12;
  /**
   * The DrawingView.
   */
  protected final DrawingView drawingView;
  /**
   * The current scale factor.
   */
  protected double scaleFactor = 1.0;
  /**
   * The scale factor for the horizontal ruler.
   */
  protected double horizontalRulerScale = Origin.DEFAULT_SCALE;
  /**
   * The scale factor for the vertical ruler.
   */
  protected double verticalRulerScale = Origin.DEFAULT_SCALE;

  /**
   * Creates a new instance.
   *
   * @param drawingView The drawing view.
   */
  private Ruler(DrawingView drawingView) {
    this.drawingView = requireNonNull(drawingView, "drawingView");

  }

  /**
   * A horizontal ruler.
   */
  public static class Horizontal
      extends Ruler {

    /**
     * Creates a new instance.
     *
     * @param drawingView The drawing view.
     */
    public Horizontal(DrawingView drawingView) {
      super(drawingView);
    }

    /**
     * Sets a new width of the ruler and repaints it.
     *
     * @param preferredWidth The new width.
     */
    public void setPreferredWidth(int preferredWidth) {
      setPreferredSize(new Dimension(preferredWidth, SIZE));
      repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);

      Rectangle drawHere = g.getClipBounds();
//      Point translation = (Point) drawingView.getTranslation().clone();
      Point translation = new Point((int) -drawingView.getDrawingToViewTransform().getTranslateX(),
                                    (int) -drawingView.getDrawingToViewTransform().getTranslateY());
      // if we scroll right the translation isn't incremented by default
      // we use the translation of the visible rect instead
      int visibleRectX = drawingView.getComponent().getVisibleRect().x + STANDARD_TRANSLATION;
      if (STANDARD_TRANSLATION == translation.x) {
        translation.x = visibleRectX;
      }

      Graphics2D g2d = (Graphics2D) g;
      g2d.setFont(new Font("Arial", Font.PLAIN, 10));
      // i translated
      int translated;
      // i normalized to decimal
      int draw;
      int drawOld = 0;
      // draw translated
      int drawTranslated;
      String translatedAsString;
      String lastIndex;

      // base line
      g2d.drawLine(0, SIZE - 1,
                   getWidth(), SIZE - 1);

      for (int i = drawHere.x; i < getWidth(); i += 10) {
        translated = translateValue(i, translation);
        translatedAsString = Integer.toString(translated);
        lastIndex = translatedAsString.substring(translatedAsString.length() - 1);

        int decimal = Integer.parseInt(lastIndex);
        {
          // These steps are neccessary to guarantee lines are drawn
          // at every pixel. It always rounds i to a decimal, so the modulo
          // operators work
          draw = i;

          if (translated < 0) {
            draw += decimal;
          }
          else {
            draw -= decimal;
          }

          drawTranslated = translateValue(draw, translation);
          // draw has to be incremented by 1, otherwise the drawn lines
          // are wrong by 1 pixel
          draw++;
        }

        if (drawTranslated % (10 * scaleFactor) == 0) {
          g2d.drawLine(draw, SIZE - 1, draw, SIZE - 4);
        }

        if (drawTranslated % (50 * scaleFactor) == 0) {
          g2d.drawLine(draw, SIZE - 1, draw, SIZE - 7);
        }

        if (drawTranslated % (100 * scaleFactor) == 0) {
          g2d.drawLine(draw, SIZE - 1, draw, SIZE - 11);
          int value = (int) (drawTranslated / scaleFactor) * (int) horizontalRulerScale;
          String textValue = Integer.toString(value);
          if (scaleFactor < 0.06) {
            if (value % 5000 == 0) {
              g2d.drawString(textValue, value == 0 ? draw - 2 : draw - 8, 9);
            }
          }
          else if ((draw - drawOld) < 31) {
            if (value % 500 == 0) {
              g2d.drawString(textValue, value == 0 ? draw - 2 : draw - 8, 9);
            }
          }
          else {
            g2d.drawString(textValue, value == 0 ? draw - 2 : draw - 8, 9);
          }

          drawOld = draw;
        }
      }

    }

    /**
     * Returns a translated value, considering current translation of the view.
     *
     * @param i The value.
     * @return The translated value.
     */
    private int translateValue(int i, Point translation) {
      if (translation.x < 0) {
        return i + translation.x;
      }
      else {
        return i;
      }
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
      if (evt.getPropertyName().equals("scaleFactor")) {
        scaleFactor = (double) evt.getNewValue();
        SwingUtilities.invokeLater(new Runnable() {

          @Override
          public void run() {
            setPreferredWidth(drawingView.getComponent().getWidth());
          }
        });

      }
    }

    @Override
    public void originLocationChanged(EventObject evt) {
    }

    @Override
    public void originScaleChanged(EventObject evt) {
      if (evt.getSource() instanceof Origin) {
        Origin origin = (Origin) evt.getSource();
        SwingUtilities.invokeLater(() -> {
          horizontalRulerScale = origin.getScaleX();
          repaint();
        });
      }
    }
  }

  /**
   * A vertical ruler.
   */
  public static class Vertical
      extends Ruler {

    /**
     * Creates a new instance.
     *
     * @param drawingView The drawing view.
     */
    public Vertical(DrawingView drawingView) {
      super(drawingView);
    }

    /**
     * Sets a new height of the ruler and repaints it.
     *
     * @param preferredHeight The new height.
     */
    public void setPreferredHeight(int preferredHeight) {
      setPreferredSize(new Dimension(SIZE, preferredHeight));
      repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);

      Rectangle drawHere = g.getClipBounds();
//      Point translation = (Point) drawingView.getTranslation().clone();
      Point translation = new Point((int) -drawingView.getDrawingToViewTransform().getTranslateX(),
                                    (int) -drawingView.getDrawingToViewTransform().getTranslateY());
      // if we scroll downwards the translation isn't incremented by default
      // we use the translation of the visible rect instead
      if (translation.y == STANDARD_TRANSLATION) {
        translation.y = drawingView.getComponent().getVisibleRect().y + STANDARD_TRANSLATION;
      }

      Graphics2D g2d = (Graphics2D) g;
      g2d.setFont(new Font("Arial", Font.PLAIN, 10));
      // i translated
      int translated;
      // i normalized to decimal
      int draw;
      int drawOld = 0;
      // draw translated
      int drawTranslated;
      String translatedAsString;
      String lastIndex;

      // base line
      g2d.drawLine(
          SIZE - 1, 0,
          SIZE - 1, getHeight());

      // Rotate the font for vertical axis
      AffineTransform fontAT = new AffineTransform();
      fontAT.rotate(270 * java.lang.Math.PI / 180);
      Font font = g2d.getFont().deriveFont(fontAT);
      g2d.setFont(font);

      for (int i = drawHere.y; i < getHeight(); i += 10) {
        translated = translateValue(i, translation);
        translatedAsString = Integer.toString(translated);
        lastIndex = translatedAsString.substring(translatedAsString.length() - 1);
        int decimal = Integer.parseInt(lastIndex);

        {
          // These steps are neccessary to guarantee lines are drawn
          // at every pixel. It always rounds i to a decimal, so the modulo
          // operators work
          draw = i;

          if (translated < 0) {
            draw += decimal;
          }
          else {
            draw -= decimal;
          }

          drawTranslated = translateValue(draw, translation);
          draw++;
        }

        if (drawTranslated % (10 * scaleFactor) == 0) {
          g2d.drawLine(SIZE - 1, draw, SIZE - 4, draw);
        }

        if (drawTranslated % (50 * scaleFactor) == 0) {
          g2d.drawLine(SIZE - 1, draw, SIZE - 7, draw);
        }

        if (drawTranslated % (100 * scaleFactor) == 0) {
          g2d.drawLine(SIZE - 1, draw, SIZE - 11, draw);
          int value = -(int) (drawTranslated / scaleFactor) * (int) verticalRulerScale;
          String textValue = Integer.toString(value);

          if (scaleFactor < 0.06) {
            if (value % 5000 == 0) {
              g2d.drawString(textValue, 9, value == 0 ? draw + 2 : draw + 8);
            }
          }
          else if ((draw - drawOld) < 31) {
            if (value % 500 == 0) {
              g2d.drawString(textValue, 9, value == 0 ? draw + 2 : draw + 8);
            }
          }
          else {
            g2d.drawString(textValue, 9, value == 0 ? draw + 2 : draw + 8);
          }

          drawOld = draw;
        }
      }
    }

    /**
     * Returns a translated value, considering current translation of the view.
     *
     * @param i The value.
     * @return The translated value.
     */
    private int translateValue(int i, Point translation) {
      if (translation.y < 0) {
        return i + translation.y;
      }
      else {
        return i;
      }
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
      if (evt.getPropertyName().equals("scaleFactor")) {
        scaleFactor = (double) evt.getNewValue();
        SwingUtilities.invokeLater(new Runnable() {

          @Override
          public void run() {
            setPreferredHeight(drawingView.getComponent().getHeight());
          }
        });

      }
    }

    @Override
    public void originLocationChanged(EventObject evt) {
    }

    @Override
    public void originScaleChanged(EventObject evt) {
      if (evt.getSource() instanceof Origin) {
        Origin origin = (Origin) evt.getSource();
        SwingUtilities.invokeLater(() -> {
          verticalRulerScale = origin.getScaleY();
          repaint();
        });
      }
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/MovementCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Point;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.Route.Step;

/**
 * A command for moving a step.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface MovementCommand {

  /**
   * A constant indicating there is no operation to be executed after moving.
   */
  String NO_OPERATION = DriveOrder.Destination.OP_NOP;
  /**
   * A constant indicating the vehicle should basically just move to a point
   * without a location associated to it.
   */
  String MOVE_OPERATION = DriveOrder.Destination.OP_MOVE;
  /**
   * A constant for parking the vehicle. (Again, basically doing nothing at the destination.)
   */
  String PARK_OPERATION = DriveOrder.Destination.OP_PARK;

  /**
   * Returns the route that this movement belongs to.
   *
   * @return The route that this movement belongs to.
   */
  @Nonnull
  Route getRoute();

  /**
   * Returns the step describing the movement.
   *
   * @return The step describing the movement.
   */
  @Nonnull
  Step getStep();

  /**
   * Returns the operation to be executed after moving.
   *
   * @return The operation to be executed after moving.
   */
  @Nonnull
  String getOperation();

  /**
   * Checks whether an operation is to be executed in addition to moving or not.
   *
   * @return <code>true</code> if, and only if, no operation is to be executed.
   */
  boolean isWithoutOperation();

  /**
   * Returns the location at which the operation is to be executed. (May be
   * <code>null</code> if <em>operation</em> is <code>NO_OPERATION</code>.)
   *
   * @return The location at which the operation is to be executed.
   */
  @Nullable
  Location getOpLocation();

  /**
   * Indicates whether this movement is the final one in the driver order it belongs to.
   *
   * @return <code>true</code> if, and only if, this movement is the final one.
   */
  boolean isFinalMovement();

  /**
   * Returns the final destination of the drive order this MovementCommand was
   * created for.
   *
   * @return The final destination of the drive order this MovementCommand was
   * created for.
   */
  @Nonnull
  Point getFinalDestination();

  /**
   * Returns the destination location of the whole drive order.
   *
   * @return The destination location of the whole drive order.
   */
  @Nullable
  Location getFinalDestinationLocation();

  /**
   * Returns the operation to be executed at the <em>final</em> destination
   * position.
   *
   * @return The operation to be executed at the <em>final</em> destination
   * position.
   */
  @Nonnull
  String getFinalOperation();

  /**
   * Returns the properties of the order this command is part of.
   *
   * @return The properties of the order this command is part of.
   */
  @Nonnull
  Map<String, String> getProperties();
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/PeripheralOperationPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import java.awt.event.ItemEvent;
import java.util.Comparator;
import java.util.Optional;
import javax.swing.JPanel;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.model.PeripheralOperationModel;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.gui.StringListCellRenderer;

/**
 * User interface for a single line text.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralOperationPanel
    extends JPanel
    implements DetailsDialogContent {

  private static final Comparator<LocationModel> BY_NAME
      = (o1, o2) -> o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());
  /**
   * The bundle to be used.
   */
  private final ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverview.PROPERTIES_PATH);

  /**
   * Creates new form StringPanel.
   *
   * @param model The current system model.
   */
  public PeripheralOperationPanel(SystemModel model) {
    initComponents();

    model.getLocationModels().stream()
        .sorted(BY_NAME)
        .forEach(locationComboBox::addItem);
    loadOperations();

    //Load triggers
    for (PeripheralOperation.ExecutionTrigger trigger
             : PeripheralOperation.ExecutionTrigger.values()) {
      triggerComboBox.addItem(trigger);
    }
  }

  private void loadOperations() {
    LocationModel location = (LocationModel) locationComboBox.getSelectedItem();
    if (location == null) {
      return;
    }

    operationComboBox.removeAllItems();
    for (String op : location.getLocationType().getPropertyAllowedPeripheralOperations().getItems()) {
      operationComboBox.addItem(op);
    }
  }

  @Override
  public void updateValues() {
  }

  @Override
  public String getTitle() {
    return bundle.getString("peripheralOperationPanel.title");
  }

  @Override
  public void setProperty(Property property) {
  }

  @Override
  public Property getProperty() {
    return null;
  }

  public Optional<PeripheralOperationModel> getPeripheralOperationModel() {
    if (!isSelectionValid()) {
      return Optional.empty();
    }

    return Optional.of(new PeripheralOperationModel(
        ((LocationModel) locationComboBox.getSelectedItem()).getName(),
        (String) operationComboBox.getSelectedItem(),
        (PeripheralOperation.ExecutionTrigger) triggerComboBox.getSelectedItem(),
        requireCompleteCheckBox.isSelected()));
  }

  public void setPeripheralOpartionModel(PeripheralOperationModel model) {
    //Set location
    for (int i = 0; i < locationComboBox.getItemCount(); i++) {
      LocationModel location = locationComboBox.getItemAt(i);
      if (location.getName().equals(model.getLocationName())) {
        locationComboBox.setSelectedIndex(i);
      }
    }
    operationComboBox.setSelectedItem(model.getOperation());
    triggerComboBox.setSelectedItem(model.getExecutionTrigger());
    requireCompleteCheckBox.setSelected(model.isCompletionRequired());
  }

  private boolean isSelectionValid() {
    return locationComboBox.getSelectedItem() != null
        && operationComboBox.getSelectedItem() != null
        && triggerComboBox.getSelectedItem() != null;
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    locationLabel = new javax.swing.JLabel();
    operationLabel = new javax.swing.JLabel();
    triggerLabel = new javax.swing.JLabel();
    requireCompleteLabel = new javax.swing.JLabel();
    requireCompleteCheckBox = new javax.swing.JCheckBox();
    locationComboBox = new javax.swing.JComboBox<>();
    operationComboBox = new javax.swing.JComboBox<>();
    triggerComboBox = new javax.swing.JComboBox<>();

    setLayout(new java.awt.GridBagLayout());

    locationLabel.setFont(locationLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/panels/propertyEditing"); // NOI18N
    locationLabel.setText(bundle.getString("peripheralOperationPanel.label_location.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(locationLabel, gridBagConstraints);

    operationLabel.setFont(operationLabel.getFont());
    operationLabel.setText(bundle.getString("peripheralOperationPanel.label_operation.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(operationLabel, gridBagConstraints);

    triggerLabel.setFont(triggerLabel.getFont());
    triggerLabel.setText(bundle.getString("peripheralOperationPanel.label_trigger.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(triggerLabel, gridBagConstraints);

    requireCompleteLabel.setFont(requireCompleteLabel.getFont());
    requireCompleteLabel.setText(bundle.getString("peripheralOperationPanel.label_requireComplete.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(requireCompleteLabel, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(requireCompleteCheckBox, gridBagConstraints);

    locationComboBox.setPreferredSize(new java.awt.Dimension(200, 22));
    locationComboBox.setRenderer(new StringListCellRenderer<LocationModel>(locationModel -> locationModel.getName()));
    locationComboBox.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        locationComboBoxItemStateChanged(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(locationComboBox, gridBagConstraints);

    operationComboBox.setPreferredSize(new java.awt.Dimension(200, 22));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(operationComboBox, gridBagConstraints);

    triggerComboBox.setPreferredSize(new java.awt.Dimension(200, 22));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(triggerComboBox, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents

  private void locationComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_locationComboBoxItemStateChanged
    if (evt.getStateChange() == ItemEvent.SELECTED) {
      loadOperations();
    }
  }//GEN-LAST:event_locationComboBoxItemStateChanged

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<LocationModel> locationComboBox;
  private javax.swing.JLabel locationLabel;
  private javax.swing.JComboBox<String> operationComboBox;
  private javax.swing.JLabel operationLabel;
  private javax.swing.JCheckBox requireCompleteCheckBox;
  private javax.swing.JLabel requireCompleteLabel;
  private javax.swing.JComboBox<PeripheralOperation.ExecutionTrigger> triggerComboBox;
  private javax.swing.JLabel triggerLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteTransportOrderService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;

/**
 * Declares the methods provided by the {@link TransportOrderService} via RMI.
 *
 * <p>
 * The majority of the methods declared here have signatures analogous to their counterparts in
 * {@link TransportOrderService}, with an additional {@link ClientID} parameter which serves the
 * purpose of identifying the calling client and determining its permissions.
 * </p>
 * <p>
 * To avoid redundancy, the semantics of methods that only pass through their arguments are not
 * explicitly documented here again. See the corresponding API documentation in
 * {@link TransportOrderService} for these, instead.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RemoteTransportOrderService
    extends RemoteTCSObjectService,
            Remote {

  // CHECKSTYLE:OFF
  OrderSequence createOrderSequence(ClientID clientId, OrderSequenceCreationTO to)
      throws RemoteException;

  TransportOrder createTransportOrder(ClientID clientId, TransportOrderCreationTO to)
      throws RemoteException;

  void markOrderSequenceComplete(ClientID clientId, TCSObjectReference<OrderSequence> ref)
      throws RemoteException;
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-API-Injection/src/main/java/org/opentcs/customizations/kernel/package-info.java<|end_filename|>
/**
 * Components supporting extension and customization of the openTCS kernel application.
 */
package org.opentcs.customizations.kernel;


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/sequences/OrderSequenceTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.sequences;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderSequenceTableModel
    extends AbstractTableModel
    implements OrderSequenceContainerListener {

  private static final Logger LOG = LoggerFactory.getLogger(OrderSequenceTableModel.class);

  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewOperating.TO_SEQUENCE_PATH);

  private static final int COLUMN_NAME = 0;
  private static final int COLUMN_INTENDED_VEHICLE = 1;
  private static final int COLUMN_EXECUTING_VEHICLE = 2;
  private static final int COLUMN_INDEX = 3;
  private static final int COLUMN_COMPLETED = 4;
  private static final int COLUMN_FINISHED = 5;
  private static final int COLUMN_FAILURE = 6;

  private static final String[] COLUMN_NAMES = {
    "Name",
    BUNDLE.getString("orderSequenceTableModel.column_intendedVehicle.headerText"),
    BUNDLE.getString("orderSequenceTableModel.column_executingVehicle.headerText"),
    "Index",
    BUNDLE.getString("orderSequenceTableModel.column_complete.headerText"),
    BUNDLE.getString("orderSequenceTableModel.column_finished.headerText"),
    BUNDLE.getString("orderSequenceTableModel.column_failureFatal.headerText")
  };

  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
    String.class,
    String.class,
    String.class,
    String.class,
    String.class,
    String.class,
    String.class
  };

  private final List<OrderSequence> entries = new LinkedList<>();

  @Override
  public int getRowCount() {
    return entries.size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= entries.size()) {
      return null;
    }

    OrderSequence entry = entries.get(rowIndex);
    switch (columnIndex) {
      case COLUMN_NAME:
        return entry.getName();

      case COLUMN_INTENDED_VEHICLE:
        if (entry.getIntendedVehicle() != null) {
          return entry.getIntendedVehicle().getName();
        }
        else {
          return BUNDLE.getString("orderSequenceTableModel.column_intendedVehicle.determinedAutomatic.text");
        }
      case COLUMN_EXECUTING_VEHICLE:

        if (entry.getProcessingVehicle() != null) {
          return entry.getProcessingVehicle().getName();
        }
        else {
          return BUNDLE.getString("orderSequenceTableModel.column_intendedVehicle.determinedAutomatic.text");
        }
      case COLUMN_INDEX:
        return entry.getFinishedIndex();
      case COLUMN_COMPLETED:
        return entry.isComplete();
      case COLUMN_FINISHED:
        return entry.isFinished();
      case COLUMN_FAILURE:
        return entry.isFailureFatal();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public void containerInitialized(Collection<OrderSequence> sequences) {
    requireNonNull(sequences, "sequences");

    SwingUtilities.invokeLater(() -> {
      // Notifiations of any change listeners must happen at the same time/in the same thread the 
      // data behind the model is updated. Otherwise, there is a risk that listeners work with/
      // refer to outdated data, which can lead to runtime exceptions.
      entries.clear();
      entries.addAll(sequences);
      fireTableDataChanged();
    });
  }

  @Override
  public void orderSequenceAdded(OrderSequence sequence) {
    requireNonNull(sequence, "sequence");

    SwingUtilities.invokeLater(() -> {
      entries.add(sequence);
      fireTableRowsInserted(entries.size() - 1, entries.size() - 1);
    });
  }

  @Override
  public void orderSequenceUpdated(OrderSequence sequence) {
    requireNonNull(sequence, "sequence");

    SwingUtilities.invokeLater(() -> {
      int sequenceIndex = entries.indexOf(sequence);
      if (sequenceIndex == -1) {
        LOG.warn("Unknown order sequence: {}. Ignoring order sequence update.", sequence.getName());
        return;
      }
      entries.set(sequenceIndex, sequence);
      fireTableRowsUpdated(sequenceIndex, sequenceIndex);
    });
  }

  @Override
  public void orderSequenceRemoved(OrderSequence sequence) {
    requireNonNull(sequence, "sequence");
    SwingUtilities.invokeLater(() -> {
      int sequenceIndex = entries.indexOf(sequence);
      if (sequenceIndex == -1) {
        LOG.warn("Unknown order sequence: {}. Ignoring order sequence removal.", sequence.getName());
        return;
      }
      entries.remove(sequenceIndex);
      fireTableRowsDeleted(sequenceIndex, sequenceIndex);
    });
  }

  /**
   * Returns the order sequence at the specified index.
   *
   * @param index the index to return.
   * @return the order sequence at that index.
   */
  public OrderSequence getEntryAt(int index) {
    if (index < 0 || index >= entries.size()) {
      return null;
    }

    return entries.get(index);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/CoordinateCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import com.google.inject.assistedinject.Assisted;
import javax.inject.Inject;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.opentcs.guing.util.UserMessageHelper;

/**
 * 
 * A cell editor for a coordinate property.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CoordinateCellEditor
    extends QuantityCellEditor {

  /**
   * Creates a new instance.
   *
   * @param textField
   */
  @Inject
  public CoordinateCellEditor(@Assisted JTextField textField, @Assisted UserMessageHelper umh) {
    super(textField, umh);
  }

  /**
   * The table cell contains (from left to right):
   * 1. An editable textfield
   * 2. A button with "arrow down" symbol to copy values from model to layout
   * 3. A button with "arrow up" symbol to copy values from layout to model
   * 4. A button with "..." symbol to open a dialog with extended editor
   * functionality.
   *
   * @return
   */
  @Override  // AbstractPropertyCellEditor
  protected JComponent createComponent() {
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    panel.add(getComponent());
    JComponent button = createButtonDetailsDialog();
    panel.add(button);

    return panel;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/KernelStateEventListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import org.opentcs.access.Kernel;

/**
 * A listener for events concerning kernel state changes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
interface KernelStateEventListener {

  /**
   * Called when the kernel state changes to {@link Kernel.State#SHUTDOWN}.
   */
  void onKernelShutdown();
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/ActiveLayerProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Provides a method to get the currently active layer.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ActiveLayerProvider {

  /**
   * Returns the {@link LayerWrapper} instance that holds the currently active layer.
   *
   * @return The currently active layer.
   */
  LayerWrapper getActiveLayer();
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/TransportOrderComparatorDeadlineAtRiskFirstTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.mockito.Mockito;
import static org.mockito.Mockito.when;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorDeadlineAtRiskFirst;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderComparatorDeadlineAtRiskFirstTest {

  private TransportOrderComparatorDeadlineAtRiskFirst comparator;

  private DefaultDispatcherConfiguration configuration;

  @Before
  public void setUp() {
    configuration = Mockito.mock(DefaultDispatcherConfiguration.class);
    when(configuration.deadlineAtRiskPeriod()).thenReturn(Long.valueOf(60 * 60 * 1000));

    comparator = new TransportOrderComparatorDeadlineAtRiskFirst(configuration);
  }

  @Test
  public void sortCriticalDeadlinesUp() {
    Instant deadline = Instant.now();
    TransportOrder plainOrder = new TransportOrder("Some order ", new ArrayList<>());
    TransportOrder order1 = plainOrder.withDeadline(deadline.plus(150, ChronoUnit.MINUTES));
    TransportOrder order2 = plainOrder.withDeadline(deadline.plus(5, ChronoUnit.MINUTES));
    TransportOrder order3 = plainOrder.withDeadline(deadline.plus(170, ChronoUnit.MINUTES));

    List<TransportOrder> list = new ArrayList<>();
    list.add(order1);
    list.add(order2);
    list.add(order3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(order2)));
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/menus/menubar/ApplicationMenuBar.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenuBar;

/**
 * The plant overview's main menu bar.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ApplicationMenuBar
    extends JMenuBar {

  private final FileMenu menuFile;
  private final ActionsMenu menuActions;
  private final ViewMenu menuView;
  private final HelpMenu menuHelp;

  /**
   * Creates a new instance.
   *
   * @param menuFile The "File" menu.
   * @param menuActions The "Actions" menu.
   * @param menuView The "View" menu.
   * @param menuHelp The "Help menu.
   */
  @Inject
  public ApplicationMenuBar(FileMenu menuFile,
                            ActionsMenu menuActions,
                            ViewMenu menuView,
                            HelpMenu menuHelp) {
    requireNonNull(menuFile, "menuFile");
    requireNonNull(menuActions, "menuActions");
    requireNonNull(menuView, "menuView");
    requireNonNull(menuHelp, "menuHelp");

    this.menuFile = menuFile;
    add(menuFile);

    this.menuActions = menuActions;
    add(menuActions);

    this.menuView = menuView;
    add(menuView);

    this.menuHelp = menuHelp;
    add(menuHelp);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Provides methods to edit layers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerEditor {

  /**
   * Sets a layer's visible state.
   *
   * @param layerId The ID of the layer.
   * @param visible The layer's new visible state.
   */
  void setLayerVisible(int layerId, boolean visible);

  /**
   * Sets a layer's name.
   *
   * @param layerId The ID of the layer.
   * @param name The layer's new name.
   */
  void setLayerName(int layerId, String name);
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/routing/edgeevaluator/EdgeEvaluatorExplicitPropertiesTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.edgeevaluator;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import org.junit.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.routing.Edge;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EdgeEvaluatorExplicitPropertiesTest {

  private EdgeEvaluatorExplicitProperties edgeEvaluator;

  private ExplicitPropertiesConfiguration configuration;

  @Before
  public void setUp() {
    configuration = mock(ExplicitPropertiesConfiguration.class);
    edgeEvaluator = new EdgeEvaluatorExplicitProperties(configuration);
  }

  @Test
  public void extractCorrectProperties() {
    Edge edge = new Edge(
        new Path("pathName",
                 new Point("srcPoint").getReference(),
                 new Point("dstPoint").getReference())
            .withProperty(Router.PROPKEY_ROUTING_COST_FORWARD + "XYZ", "1234")
            .withProperty(Router.PROPKEY_ROUTING_COST_REVERSE + "XYZ", "5678"),
        false
    );
    Vehicle vehicle = new Vehicle("someVehicle")
        .withProperty(Router.PROPKEY_ROUTING_GROUP, "XYZ");

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(1234.0));

    Edge reverseEdge = new Edge(edge.getPath(), true);

    assertThat(edgeEvaluator.computeWeight(reverseEdge, vehicle), is(5678.0));
  }

  @Test
  public void useConfiguredDefaultValue() {
    when(configuration.defaultValue()).thenReturn("123.456");

    Edge edge = new Edge(
        new Path("pathName", new Point("srcPoint").getReference(),
                 new Point("dstPoint").getReference()),
        false
    );
    Vehicle vehicle = new Vehicle("someVehicle")
        .withProperty(Router.PROPKEY_ROUTING_GROUP, "XYZ");

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(123.456));

    Edge reverseEdge = new Edge(edge.getPath(), true);

    assertThat(edgeEvaluator.computeWeight(reverseEdge, vehicle), is(123.456));
  }

  @Test
  public void handleInvalidDefaultValue() {
    when(configuration.defaultValue()).thenReturn("some invalid value");

    Edge edge = new Edge(
        new Path("pathName", new Point("srcPoint").getReference(),
                 new Point("dstPoint").getReference()),
        false
    );
    Vehicle vehicle = new Vehicle("someVehicle")
        .withProperty(Router.PROPKEY_ROUTING_GROUP, "XYZ");

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(Double.POSITIVE_INFINITY));

    Edge reverseEdge = new Edge(edge.getPath(), true);

    assertThat(edgeEvaluator.computeWeight(reverseEdge, vehicle), is(Double.POSITIVE_INFINITY));
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/exchange/adapter/VehicleAllowedOrderTypesAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.data.model.Vehicle;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.model.elements.VehicleModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Updates a vehicle's allowed order types with the kernel when it changes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleAllowedOrderTypesAdapter
    implements AttributesChangeListener {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(VehicleAllowedOrderTypesAdapter.class);
  /**
   * The vehicle model.
   */
  private final VehicleModel model;
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * The state of the plant overview.
   */
  private final ApplicationState applicationState;
  /**
   * The vehicle's allowed order types the last time we checked them.
   */
  private Set<String> previousAllowedOrderTypes;

  /**
   * Creates a new instance.
   *
   * @param portalProvider A kernel provider.
   * @param applicationState Keeps the plant overview's state.
   * @param model The vehicle model.
   */
  public VehicleAllowedOrderTypesAdapter(SharedKernelServicePortalProvider portalProvider,
                                         ApplicationState applicationState,
                                         VehicleModel model) {
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.applicationState = requireNonNull(applicationState, "applicationState");
    this.model = requireNonNull(model, "model");
    this.previousAllowedOrderTypes = getAllowedOrderTypes();
  }

  @Override
  public void propertiesChanged(AttributesChangeEvent e) {
    if (e.getModel() != model) {
      return;
    }

    Set<String> allowedOrderTypes = getAllowedOrderTypes();
    if (previousAllowedOrderTypes.size() == allowedOrderTypes.size()
        && previousAllowedOrderTypes.containsAll(allowedOrderTypes)) {
      LOG.debug("Ignoring vehicle properties update because the allowed order types did not "
          + "change");
      return;
    }

    previousAllowedOrderTypes = allowedOrderTypes;
    new Thread(() -> updateAllowedOrderTypesInKernel(allowedOrderTypes)).start();
  }

  private Set<String> getAllowedOrderTypes() {
    return model.getPropertyAllowedOrderTypes().getItems();
  }

  private void updateAllowedOrderTypesInKernel(Set<String> allowedOrderTypes) {
    try (SharedKernelServicePortal sharedPortal = portalProvider.register()) {
      KernelServicePortal portal = sharedPortal.getPortal();
      // Check if the kernel is in operating mode, too.
      if (portal.getState() == Kernel.State.OPERATING) {
        Vehicle vehicle = portal.getVehicleService().fetchObject(Vehicle.class, model.getName());
        if (vehicle.getAllowedOrderTypes().size() == allowedOrderTypes.size()
            && vehicle.getAllowedOrderTypes().containsAll(allowedOrderTypes)) {
          LOG.debug("Ignoring vehicle properties update. Already up do date.");
          return;
        }
        portal.getVehicleService().updateVehicleAllowedOrderTypes(vehicle.getReference(),
                                                                  allowedOrderTypes);
      }

    }
    catch (ServiceUnavailableException exc) {
      LOG.warn("Could not connect to kernel", exc);
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/VehicleControllerComponentsFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;

/**
 * A factory for various components related to a vehicle controller.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleControllerComponentsFactory {

  /**
   * Creates a new {@link PeripheralInteractor} instance for the given vehicle.
   *
   * @param vehicleRef The vehicle.
   * @return A new peripheral interactor.
   */
  PeripheralInteractor createPeripheralInteractor(TCSObjectReference<Vehicle> vehicleRef);
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/peripherals/LocalPeripheralEntry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.peripherals;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;

/**
 * An entry for a peripheral device registered with the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class LocalPeripheralEntry {

  /**
   * Used for implementing property change events.
   */
  private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  /**
   * The location representing the peripheral device.
   */
  private final TCSResourceReference<Location> location;
  /**
   * The description of the attached peripheral comm adapter.
   */
  private PeripheralCommAdapterDescription attachedCommAdapter;
  /**
   * The process model that describes the peripheral device's state.
   */
  private PeripheralProcessModel processModel;

  /**
   * Creates a new instance.
   *
   * @param location The location representing the peripheral device.
   * @param attachedCommAdapter The description of the attached peripheral comm adapter.
   * @param processModel The process model that describes the peripheral device's state.
   */
  public LocalPeripheralEntry(@Nonnull TCSResourceReference<Location> location,
                              @Nonnull PeripheralCommAdapterDescription attachedCommAdapter,
                              @Nonnull PeripheralProcessModel processModel) {
    this.location = requireNonNull(location, "location");
    this.attachedCommAdapter = requireNonNull(attachedCommAdapter, "attachedCommAdapter");
    this.processModel = requireNonNull(processModel, "processModel");
  }

  public void addPropertyChangeListener(PropertyChangeListener listener) {
    pcs.addPropertyChangeListener(listener);
  }

  public void removePropertyChangeListener(PropertyChangeListener listener) {
    pcs.removePropertyChangeListener(listener);
  }

  /**
   * Returns the location representing the peripheral device.
   *
   * @return The location representing the peripheral device.
   */
  @Nonnull
  public TCSResourceReference<Location> getLocation() {
    return location;
  }

  /**
   * Returns the description of the attached peripheral comm adapter.
   *
   * @return The description of the attached peripheral comm adapter.
   */
  @Nonnull
  public PeripheralCommAdapterDescription getAttachedCommAdapter() {
    return attachedCommAdapter;
  }

  public void setAttachedCommAdapter(@Nonnull PeripheralCommAdapterDescription attachedCommAdapter) {
    PeripheralCommAdapterDescription oldAttachedCommAdapter = this.attachedCommAdapter;
    this.attachedCommAdapter = requireNonNull(attachedCommAdapter, "attachedCommAdapter");

    pcs.firePropertyChange(Attribute.ATTACHED_COMM_ADAPTER.name(),
                           oldAttachedCommAdapter,
                           attachedCommAdapter);
  }

  /**
   * Returns the process model that describes the peripheral device's state.
   *
   * @return The process model that describes the peripheral device's state.
   */
  @Nonnull
  public PeripheralProcessModel getProcessModel() {
    return processModel;
  }

  public void setProcessModel(@Nonnull PeripheralProcessModel processModel) {
    PeripheralProcessModel oldProcessModel = this.processModel;
    this.processModel = requireNonNull(processModel, "processModel");

    pcs.firePropertyChange(Attribute.PROCESS_MODEL.name(),
                           oldProcessModel,
                           processModel);
  }

  /**
   * Enum elements used as notification arguments to specify which argument changed.
   */
  public static enum Attribute {
    /**
     * Indicates a change of the process model.
     */
    PROCESS_MODEL,
    /**
     * Indicates a change of the attached comm adapter.
     */
    ATTACHED_COMM_ADAPTER
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/LocalKernel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.KernelExtension;

/**
 * Declares the methods the openTCS kernel must provide which are not accessible
 * to remote peers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LocalKernel
    extends Kernel,
            Lifecycle {

  /**
   * Adds a <code>KernelExtension</code> to this kernel.
   *
   * @param newExtension The extension to be added.
   */
  void addKernelExtension(KernelExtension newExtension);

  /**
   * Removes a <code>KernelExtension</code> from this kernel.
   *
   * @param rmExtension The extension to be removed.
   */
  void removeKernelExtension(KernelExtension rmExtension);
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/peripherals/LocalPeripheralEntryPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.peripherals;

import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.ServiceCallWrapper;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentEvent;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
import org.opentcs.drivers.peripherals.management.PeripheralProcessModelEvent;
import org.opentcs.util.CallWrapper;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A pool of {@link LocalPeripheralEntry}'s for every location in the kernel that represents a
 * peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class LocalPeripheralEntryPool
    implements EventHandler,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LocalPeripheralEntryPool.class);
  /**
   * The service portal to use for kernel interactions.
   */
  private final KernelServicePortal servicePortal;
  /**
   * The call wrapper to use for service calls.
   */
  private final CallWrapper callWrapper;
  /**
   * Where this instance registers for application events.
   */
  private final EventSource eventSource;
  /**
   * The entries of this pool.
   */
  private final Map<TCSResourceReference<Location>, LocalPeripheralEntry> entries = new HashMap<>();
  /**
   * Whether the pool is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param servicePortal The service portal to use for kernel interactions.
   * @param callWrapper The call wrapper to use for service calls.
   * @param eventSource Where this instance registers for application events.
   */
  @Inject
  public LocalPeripheralEntryPool(KernelServicePortal servicePortal,
                                  @ServiceCallWrapper CallWrapper callWrapper,
                                  @ApplicationEventBus EventSource eventSource) {
    this.servicePortal = requireNonNull(servicePortal, "servicePortal");
    this.callWrapper = requireNonNull(callWrapper, "callWrapper");
    this.eventSource = requireNonNull(eventSource, "eventSource");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    try {
      initializeEntryMap();
      LOG.debug("Initialized peripheral entry pool: {}", entries);
    }
    catch (Exception e) {
      LOG.warn("Error initializing peripheral entry pool.", e);
      entries.clear();
      return;
    }

    eventSource.subscribe(this);

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventSource.unsubscribe(this);
    entries.clear();

    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof PeripheralProcessModelEvent) {
      onPeripheralProcessModelEvent((PeripheralProcessModelEvent) event);
    }
    else if (event instanceof PeripheralAttachmentEvent) {
      onPeripheralAttachmentEvent((PeripheralAttachmentEvent) event);
    }
  }

  public Map<TCSResourceReference<Location>, LocalPeripheralEntry> getEntries() {
    return entries;
  }

  private void initializeEntryMap()
      throws Exception {
    Set<Location> locations
        = callWrapper.call(() -> servicePortal.getPlantModelService().fetchObjects(Location.class));
    for (Location location : locations) {
      PeripheralAttachmentInformation ai = callWrapper.call(
          () -> servicePortal.getPeripheralService().fetchAttachmentInformation(location.getReference())
      );
      PeripheralProcessModel processModel = callWrapper.call(
          () -> servicePortal.getPeripheralService().fetchProcessModel(location.getReference()));
      entries.put(location.getReference(), new LocalPeripheralEntry(location.getReference(),
                                                                    ai.getAttachedCommAdapter(),
                                                                    processModel));
    }
  }

  private void onPeripheralProcessModelEvent(PeripheralProcessModelEvent event) {
    if (!entries.containsKey(event.getLocation())) {
      LOG.warn("Received an event for an unknown location: {}", event.getLocation().getName());
      return;
    }

    entries.get(event.getLocation()).setProcessModel(event.getProcessModel());
  }

  private void onPeripheralAttachmentEvent(PeripheralAttachmentEvent event) {
    if (!entries.containsKey(event.getLocation())) {
      LOG.warn("Received an event for an unknown location: {}", event.getLocation().getName());
      return;
    }

    entries.get(event.getLocation())
        .setAttachedCommAdapter(event.getAttachmentInformation().getAttachedCommAdapter());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/VisualLayout.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model.visualization;

import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * Describes the visual attributes of a model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VisualLayout
    extends TCSObject<VisualLayout>
    implements Serializable {

  /**
   * This layout's scale on the X axis (in mm/pixel).
   */
  private final double scaleX;
  /**
   * This layout's scale on the Y axis (in mm/pixel).
   */
  private final double scaleY;
  /**
   * VisualLayout elements describing the visualization of a model and additional
   * elements that need to be displayed.
   */
  @Deprecated
  private final Set<LayoutElement> layoutElements;
  /**
   * The layers in this model.
   */
  private final List<Layer> layers;
  /**
   * The layer groups in this model.
   */
  private final List<LayerGroup> layerGroups;

  /**
   * Creates a new VisualLayout.
   *
   * @param name This visual layout's name.
   */
  public VisualLayout(String name) {
    super(name);
    this.scaleX = 50.0;
    this.scaleY = 50.0;
    this.layoutElements = new HashSet<>();
    this.layers = new LinkedList<>();
    this.layerGroups = new LinkedList<>();
  }

  /**
   * Creates a new VisualLayout.
   *
   * @param name This visual layout's name.
   */
  @SuppressWarnings("deprecation")
  private VisualLayout(String name,
                       Map<String, String> properties,
                       ObjectHistory history,
                       double scaleX,
                       double scaleY,
                       Set<LayoutElement> layoutElements,
                       List<Layer> layers,
                       List<LayerGroup> layerGroups) {
    super(name, properties, history);
    this.scaleX = scaleX;
    this.scaleY = scaleY;
    this.layoutElements = new HashSet<>(requireNonNull(layoutElements, "layoutElements"));
    this.layers = new LinkedList<>(requireNonNull(layers, "layers"));
    this.layerGroups = new LinkedList<>(requireNonNull(layerGroups, "layerGroups"));
  }

  @Override
  public VisualLayout withProperty(String key, String value) {
    return new VisualLayout(getName(),
                            propertiesWith(key, value),
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  @Override
  public VisualLayout withProperties(Map<String, String> properties) {
    return new VisualLayout(getName(),
                            properties,
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  @Override
  public TCSObject<VisualLayout> withHistoryEntry(ObjectHistory.Entry entry) {
    return new VisualLayout(getName(),
                            getProperties(),
                            getHistory().withEntryAppended(entry),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  @Override
  public TCSObject<VisualLayout> withHistory(ObjectHistory history) {
    return new VisualLayout(getName(),
                            getProperties(),
                            history,
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  /**
   * Returns this layout's scale on the X axis (in mm/pixel).
   *
   * @return This layout's scale on the X axis.
   */
  public double getScaleX() {
    return scaleX;
  }

  /**
   * Creates a copy of this object, with the given scaleX.
   *
   * @param scaleX The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayout withScaleX(double scaleX) {
    return new VisualLayout(getName(),
                            getProperties(),
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  /**
   * Returns this layout's scale on the Y axis (in mm/pixel).
   *
   * @return This layout's scale on the Y axis.
   */
  public double getScaleY() {
    return scaleY;
  }

  /**
   * Creates a copy of this object, with the given scaleY.
   *
   * @param scaleY The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayout withScaleY(double scaleY) {
    return new VisualLayout(getName(),
                            getProperties(),
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  /**
   * Returns the layout elements describing the visualization of a model.
   *
   * @return The layout elements describing the visualization of a model.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public Set<LayoutElement> getLayoutElements() {
    return layoutElements;
  }

  /**
   * Creates a copy of this object, with the given layoutElements.
   *
   * @param layoutElements The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public VisualLayout withLayoutElements(Set<LayoutElement> layoutElements) {
    return new VisualLayout(getName(),
                            getProperties(),
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  /**
   * Returns the layers of this layout.
   *
   * @return The layers of this layout.
   */
  public List<Layer> getLayers() {
    return layers;
  }

  /**
   * Creates a copy of this object, with the given layers.
   *
   * @param layers The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayout withLayers(List<Layer> layers) {
    return new VisualLayout(getName(),
                            getProperties(),
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }

  /**
   * Returns the layer groups of this layout.
   *
   * @return The layer groups of this layout.
   */
  public List<LayerGroup> getLayerGroups() {
    return layerGroups;
  }

  /**
   * Creates a copy of this object, with the given layer groups.
   *
   * @param layerGroups The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayout withLayerGroups(List<LayerGroup> layerGroups) {
    return new VisualLayout(getName(),
                            getProperties(),
                            getHistory(),
                            scaleX,
                            scaleY,
                            layoutElements,
                            layers,
                            layerGroups);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/commands/InitPositionCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.commands;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.SimVehicleCommAdapter;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A command for initializing the comm adapter's position.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class InitPositionCommand
    implements AdapterCommand {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(InitPositionCommand.class);
  /**
   * The position to set.
   */
  private final String position;

  /**
   * Creates a new instance.
   *
   * @param position The position to set.
   */
  public InitPositionCommand(@Nonnull String position) {
    this.position = requireNonNull(position, "position");
  }

  @Override
  public void execute(VehicleCommAdapter adapter) {
    if (!(adapter instanceof SimVehicleCommAdapter)) {
      LOG.warn("Adapter is not a SimVehicleCommAdapter: {}", adapter);
      return;
    }

    ((SimVehicleCommAdapter) adapter).initVehiclePosition(position);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/event/TableSelectionChangeEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.event;

import java.util.EventObject;
import org.opentcs.guing.components.properties.table.AttributesTable;

/**
 * An Event emitted when a line in a table is selected.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class TableSelectionChangeEvent
    extends EventObject {

  /**
   * The attribute.
   */
  protected Object fSelectedValue;

  /**
   * Creates a new instance of TableSelectionChangeEvent
   */
  public TableSelectionChangeEvent(AttributesTable table, Object selectedValue) {
    super(table);
    fSelectedValue = selectedValue;
  }

  /**
   * Returns the attribute contained in the selected line.
   */
  public Object getSelectedValue() {
    return fSelectedValue;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/PluginPanelManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import org.opentcs.components.plantoverview.PluggablePanelFactory;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PluginPanelManager {

  /**
   * Shows or hides the specific {@code PanelFactory}.
   *
   * @param factory The factory resp. panel that shall be shown / hidden.
   * @param visible True to set it visible, false otherwise.
   */
  public void showPluginPanel(PluggablePanelFactory factory, boolean visible);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/event/EventSource.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.event;

/**
 * A source of events that can be subscribed to.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface EventSource {

  /**
   * Subscribes the given listener to events emitted by this source.
   *
   * @param listener The listener to be subscribed.
   */
  void subscribe(EventHandler listener);

  /**
   * Unsubscribes the given listener.
   *
   * @param listener The listener to be unsubscribed.
   */
  void unsubscribe(EventHandler listener);
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/SetPrecisePositionCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import javax.annotation.Nullable;
import org.opentcs.data.model.Triple;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;

/**
 * A command to set a vehicle's precise position.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetPrecisePositionCommand
    implements AdapterCommand {

  /**
   * The percise position to set.
   */
  private final Triple position;

  /**
   * Creates a new instance.
   *
   * @param position The precise position to set.
   */
  public SetPrecisePositionCommand(@Nullable Triple position) {
    this.position = position;
  }

  @Override
  public void execute(VehicleCommAdapter adapter) {
    adapter.getProcessModel().setVehiclePrecisePosition(position);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/ModelComponentUtil.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import java.util.ArrayList;
import java.util.List;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.model.CompositeModelComponent;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;

/**
 * Provides utility methods for {@link ModelComponent}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelComponentUtil {

  /**
   * Prevent instantiation.
   */
  private ModelComponentUtil() {
  }

  public static List<Figure> getChildFigures(CompositeModelComponent parent,
                                             SystemModel systemModel) {
    List<Figure> figures = new ArrayList<>();

    List<ModelComponent> childComps = parent.getChildComponents();
    synchronized (childComps) {
      for (ModelComponent component : childComps) {
        Figure figure = systemModel.getFigure(component);
        if (figure != null) {
          figures.add(figure);
        }
      }
    }

    return figures;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/MovementCommandImpl.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Point;
import org.opentcs.data.order.Route;
import org.opentcs.drivers.vehicle.MovementCommand;

/**
 * The default movement command implementation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class MovementCommandImpl
    implements MovementCommand {

  /**
   * The route that this movement belongs to.
   */
  private final Route route;
  /**
   * The step describing the movement.
   */
  private final Route.Step step;
  /**
   * The operation to be executed after moving.
   */
  private final String operation;
  /**
   * The location at which the operation is to be executed. (May be
   * <code>null</code> if <em>operation</em> is <code>NO_OPERATION</code>.)
   */
  private final Location opLocation;
  /**
   * Indicates whether this movement is the final one for the drive order it belongs to.
   */
  private final boolean finalMovement;
  /**
   * The destination position of the whole drive order.
   */
  private final Point finalDestination;
  /**
   * The destination location of the whole drive order.
   */
  private final Location finalDestinationLocation;
  /**
   * The operation to be executed at the destination position.
   */
  private final String finalOperation;
  /**
   * Properties of the order this command is part of.
   */
  private final Map<String, String> properties;

  /**
   * Creates a new instance.
   *
   * @param route The route that this movement belongs to.
   * @param step The step describing the movement.
   * @param operation The operation to be executed after moving.
   * @param opLocation The location at which the operation is to be executed.
   * May be <code>null</code> if <em>newOperation</em> is <code>NO_OPERATION</code>.)
   * @param finalMovement Indicates whether this movement is the final one in the drive order it
   * belongs to.
   * @param finalDestinationLocation The destination location of the whole drive order.
   * @param finalDestination The destination position of the whole drive order.
   * @param finalOperation The operation to be executed at the destination
   * position.
   * @param properties Properties of the order this command is part of.
   */
  @SuppressWarnings("deprecation")
  public MovementCommandImpl(Route route,
                             Route.Step step,
                             String operation,
                             Location opLocation,
                             boolean finalMovement,
                             Location finalDestinationLocation,
                             Point finalDestination,
                             String finalOperation,
                             Map<String, String> properties) {
    this.step = requireNonNull(step, "step");
    this.operation = requireNonNull(operation, "operation");
    this.finalMovement = finalMovement;
    this.finalDestinationLocation = finalDestinationLocation;
    this.finalDestination = requireNonNull(finalDestination, "finalDestination");
    this.finalOperation = requireNonNull(finalOperation, "finalOperation");
    this.properties = requireNonNull(properties, "properties");
    if (opLocation == null && !isEmptyOperation(operation)) {
      throw new NullPointerException("opLocation");
    }
    this.opLocation = opLocation;

    this.route = requireNonNull(route, "route");
  }

  @Override
  public Route getRoute() {
    return route;
  }

  @Nonnull
  @Override
  public Route.Step getStep() {
    return step;
  }

  @Nonnull
  @Override
  public String getOperation() {
    return operation;
  }

  @Override
  public boolean isWithoutOperation() {
    return isEmptyOperation(operation);
  }

  @Nullable
  @Override
  public Location getOpLocation() {
    return opLocation;
  }

  @Override
  public boolean isFinalMovement() {
    return finalMovement;
  }

  @Nonnull
  @Override
  public Point getFinalDestination() {
    return finalDestination;
  }

  @Nullable
  @Override
  public Location getFinalDestinationLocation() {
    return finalDestinationLocation;
  }

  @Nonnull
  @Override
  public String getFinalOperation() {
    return finalOperation;
  }

  @Nonnull
  @Override
  public Map<String, String> getProperties() {
    return properties;
  }

  @Override
  public boolean equals(Object o) {
    if (o instanceof MovementCommand) {
      MovementCommand other = (MovementCommand) o;
      return step.equals(other.getStep()) && operation.equals(other.getOperation());
    }
    else {
      return false;
    }
  }

  @Override
  public int hashCode() {
    return step.hashCode() ^ operation.hashCode();
  }

  @Override
  public String toString() {
    return "MovementCommandImpl{"
        + "route=" + getRoute()
        + ", step=" + getStep()
        + ", operation=" + getOperation()
        + ", opLocation=" + getOpLocation()
        + ", finalMovement=" + isFinalMovement()
        + ", finalDestination=" + getFinalDestination()
        + ", finalDestinationLocation=" + getFinalDestinationLocation()
        + ", finalOperation=" + getFinalOperation()
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Checks whether an operation means something is to be done in addition to
   * moving or not.
   *
   * @param operation The operation to be checked.
   * @return <code>true</code> if, and only if, the vehicle should only move
   * with the given operation.
   */
  private static boolean isEmptyOperation(String operation) {
    return NO_OPERATION.equals(operation)
        || MOVE_OPERATION.equals(operation)
        || PARK_OPERATION.equals(operation);
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/commands/SetPeripheralPausedCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback.commands;

import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;

/**
 * A command to pause/unpause the peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetPeripheralPausedCommand
    implements PeripheralAdapterCommand {

  /**
   * Whether to pause/unpause the peripheral device.
   */
  private final boolean paused;

  /**
   * Creates a new instance.
   *
   * @param paused Whether to pause/unpause the peripheral device.
   */
  public SetPeripheralPausedCommand(boolean paused) {
    this.paused = paused;
  }

  @Override
  public void execute(PeripheralCommAdapter adapter) {
    if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
      return;
    }

    LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
    loopbackAdapter.pausePeripheral(paused);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/util/VehicleCourseObjectFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.guing.components.drawing.figures.NamedVehicleFigure;
import org.opentcs.guing.components.drawing.figures.VehicleFigure;
import org.opentcs.guing.components.drawing.figures.VehicleFigureFactory;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * A factory for Figures and ModelComponents.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleCourseObjectFactory
    extends CourseObjectFactory  {

  /**
   * A factory for figures.
   */
  private final VehicleFigureFactory figureFactory;

  /**
   * Creates a new instance.
   *
   * @param figureFactory A factory for figures.
   */
  @Inject
  public VehicleCourseObjectFactory(VehicleFigureFactory figureFactory) {
    super(figureFactory);
    this.figureFactory = requireNonNull(figureFactory, "figureFactory");
  }

  public VehicleFigure createVehicleFigure(VehicleModel model) {
    return figureFactory.createVehicleFigure(model);
  }

  public NamedVehicleFigure createNamedVehicleFigure(VehicleModel model) {
    return figureFactory.createNamedVehicleFigure(model);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/ApplicationState.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;

/**
 * Keeps and provides information about the current state of the application as
 * a whole.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ApplicationState {

  /**
   * The application's current mode of operation.
   */
  private OperationMode operationMode = OperationMode.UNDEFINED;

  /**
   * Creates a new instance.
   */
  @Inject
  public ApplicationState() {
  }

  /**
   * Returns the application's current mode of operation.
   *
   * @return The application's current mode of operation.
   */
  public OperationMode getOperationMode() {
    return operationMode;
  }

  /**
   * Checks whether the application is currently in the given mode of operation.
   *
   * @param mode The mode to check for.
   * @return <code>true</code> if, and only if, the application is currently in
   * the given mode.
   */
  public boolean hasOperationMode(OperationMode mode) {
    return operationMode == mode;
  }

  /**
   * Sets the application's current mode of operation.
   *
   * @param operationMode The application's new mode of operation.
   */
  public void setOperationMode(OperationMode operationMode) {
    this.operationMode = requireNonNull(operationMode, "operationMode");
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/drawing/figures/NamedVehicleFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import com.google.inject.assistedinject.Assisted;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.inject.Inject;
import javax.swing.SwingUtilities;
import org.jhotdraw.draw.Figure;
import org.opentcs.components.plantoverview.VehicleTheme;
import org.opentcs.data.model.Triple;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.menus.MenuFactory;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.PlantOverviewOperatingApplicationConfiguration;

/**
 * A vehicle figure that adds the name of the vehicle into the image.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NamedVehicleFigure
    extends VehicleFigure {

  @Inject
  public NamedVehicleFigure(VehicleTheme vehicleTheme,
                            MenuFactory menuFactory,
                            PlantOverviewOperatingApplicationConfiguration appConfig,
                            @Assisted VehicleModel model,
                            ToolTipTextGenerator textGenerator,
                            ModelManager modelManager,
                            ApplicationState applicationState) {
    super(vehicleTheme,
          menuFactory,
          appConfig,
          model,
          textGenerator,
          modelManager,
          applicationState);
  }

  @Override
  protected void drawFill(Graphics2D g2d) {
    super.drawFill(g2d);
    g2d.setFont(getVehicleTheme().labelFont());
    g2d.setPaint(getVehicleTheme().labelColor());
    g2d.drawString(getVehicleTheme().label(getModel().getVehicle()),
                   (int) displayBox().getCenterX() + getVehicleTheme().labelOffsetX(),
                   (int) displayBox().getCenterY() + getVehicleTheme().labelOffsetY());
  }

  @Override
  protected void updateFigureDetails(VehicleModel model) {
    super.updateFigureDetails(model);

    fImage = getVehicleTheme().statefulImage(model.getVehicle());

    PointModel point = model.getPoint();
    Triple precisePosition = model.getPrecisePosition();

    if (point == null && precisePosition == null) {
      // If neither the point nor the precise position is known, don't draw the figure.
      SwingUtilities.invokeLater(() -> setVisible(false));
    }
    else if (precisePosition != null && !isIgnorePrecisePosition()) {
      // If a precise position exists, it is set in setBounds(), so it doesn't need any coordinates.
      SwingUtilities.invokeLater(() -> {
        setVisible(true);
        setBounds(new Point2D.Double(), null);
      });

      setFigureDetailsChanged(true);
    }
    else if (point != null) {
      SwingUtilities.invokeLater(() -> {
        setVisible(true);
        Figure pointFigure = getModelManager().getModel().getFigure(point);
        Rectangle2D.Double r = pointFigure.getBounds();
        Point2D.Double pCenter = new Point2D.Double(r.getCenterX(), r.getCenterY());
        // Draw figure in the center of the node.
        // Angle is set in setBounds().
        setBounds(pCenter, null);
      });

      setFigureDetailsChanged(true);
    }
    else {
      SwingUtilities.invokeLater(() -> setVisible(false));
    }
  }

  @Override
  public boolean isVisible() {
    if (getModel().getPoint() == null) {
      return super.isVisible();
    }

    return super.isVisible()
        && getModelManager().getModel().getFigure(getModel().getPoint()).isVisible();
  }

  @Override
  public int getLayer() {
    return FigureOrdinals.VEHICLE_FIGURE_ORDINAL;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/SelectionPropertyEditorPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import static java.util.Objects.requireNonNull;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.type.AbstractProperty;
import org.opentcs.guing.components.properties.type.ModelAttribute;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.components.properties.type.Selectable;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Panel for selecting a property from a combo box.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class SelectionPropertyEditorPanel
    extends JPanel
    implements DetailsDialogContent {

  private final ListCellRenderer<Object> listCellRenderer;
  /**
   * Das Attribut.
   */
  private AbstractProperty fProperty;

  /**
   * Creates new form SelectionPropertyEditorPanel
   */
  @SuppressWarnings("unchecked")
  public SelectionPropertyEditorPanel(ListCellRenderer<?> listCellRenderer) {
    requireNonNull(listCellRenderer, "listCellRenderer");
    
    this.listCellRenderer = (ListCellRenderer<Object>) listCellRenderer;
    initComponents();
  }

  @Override // DetailsDialogContent
  public void setProperty(Property property) {
    fProperty = (AbstractProperty) property;

    @SuppressWarnings("unchecked")
    ComboBoxModel<Object> model
        = new DefaultComboBoxModel<>(((Selectable<Object>) fProperty).getPossibleValues().toArray());
    valueComboBox.setModel(model);

    Object value = fProperty.getValue();
    valueComboBox.setSelectedItem(value);
    valueComboBox.setRenderer(listCellRenderer);
  }

  @Override // DetailsDialogContent
  public void updateValues() {
    Object selectedItem = valueComboBox.getSelectedItem();
    fProperty.setValue(selectedItem);
    fProperty.setChangeState(ModelAttribute.ChangeState.DETAIL_CHANGED);
  }

  @Override // DetailsDialogContent
  public String getTitle() {
    return ResourceBundleUtil.getBundle(I18nPlantOverview.PROPERTIES_PATH)
        .getString("selectionPropertyEditorPanel.title");
  }

  @Override // DetailsDialogContent
  public Property getProperty() {
    return fProperty;
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    valueLabel = new javax.swing.JLabel();
    valueComboBox = new javax.swing.JComboBox<>();

    setLayout(new java.awt.GridBagLayout());

    valueLabel.setFont(valueLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/panels/propertyEditing"); // NOI18N
    valueLabel.setText(bundle.getString("selectionPropertyEditorPanel.label_value.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
    add(valueLabel, gridBagConstraints);

    valueComboBox.setFont(valueComboBox.getFont());
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 0.5;
    gridBagConstraints.insets = new java.awt.Insets(4, 0, 4, 4);
    add(valueComboBox, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<Object> valueComboBox;
  private javax.swing.JLabel valueLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/kernel/workingset/NotificationBufferTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
/*
 *
 * Created on May 19, 2006, 11:48 AM
 */
package org.opentcs.kernel.workingset;

import java.util.List;
import org.junit.*;
import static org.junit.Assert.assertEquals;
import org.opentcs.data.notification.UserNotification;
import org.opentcs.util.event.SimpleEventBus;

/**
 * A test class for NotificationBuffer.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NotificationBufferTest {

  /**
   * A constant capacity for buffers to be tested here.
   */
  private static final int CAPACITY = 100;
  /**
   * The buffer to be tested here.
   */
  private NotificationBuffer testBuffer;

  @Before
  public void setUp() {
    testBuffer = new NotificationBuffer(new SimpleEventBus());
    testBuffer.setCapacity(CAPACITY);
  }

  @After
  public void tearDown() {
    testBuffer = null;
  }

  /**
   * Verifies that getMessageCount() returns the correct number.
   */
  @Test
  public void testMessageCountValidity() {
    int cutBackCount = CAPACITY / 2;
    testBuffer.setCutBackCount(cutBackCount);
    // Fill the buffer to its capacity.
    for (int i = 1; i <= CAPACITY; i++) {
      testBuffer.addNotification(new UserNotification("message text",
                                                      UserNotification.Level.INFORMATIONAL));
      assertEquals(i, testBuffer.getMessageCount());
      List<UserNotification> messages = testBuffer.getNotifications();
      assertEquals(i, messages.size());
    }
    // Add one more message to exceed the capacity.
    testBuffer.addNotification(new UserNotification("message text", UserNotification.Level.INFORMATIONAL));
    assertEquals(cutBackCount, testBuffer.getMessageCount());
    List<UserNotification> messages = testBuffer.getNotifications();
    assertEquals(cutBackCount, messages.size());
  }

  /**
   * Verify the buffer's capacity and its cut back count.
   */
  @Test
  public void testCapacityAndCutBackCount() {
    for (int cutBackCount = 0; cutBackCount < CAPACITY; cutBackCount++) {
      testBuffer.setCutBackCount(cutBackCount);
      // Add one more message than the buffer can hold.
      for (int i = 0; i < (CAPACITY + 1); i++) {
        testBuffer.addNotification(new UserNotification("message text",
                                                        UserNotification.Level.INFORMATIONAL));
      }
      // The number of messages should now be equal to the buffer's capacity.
      assertEquals(cutBackCount, testBuffer.getMessageCount());
      testBuffer.clear();
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/dialogs/StandardDialog.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dialogs;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Insets;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.border.EmptyBorder;
import org.opentcs.util.gui.Icons;

/**
 * A dialog with an ok and a cancel button.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class StandardDialog
    extends JDialog {

  /**
   * A return status code - returned if Cancel button has been pressed
   */
  public static final int RET_CANCEL = 0;
  /**
   * A return status code - returned if OK button has been pressed
   */
  public static final int RET_OK = 1;
  /**
   * The content of this dialog.
   */
  protected JComponent fContent;
  private int returnStatus = RET_CANCEL;

  /**
   * Creates a new instance.
   *
   * @param parent The parent component.
   * @param modal Whether or not the dialog is modal.
   * @param content The content component.
   * @param title The title of the dialog.
   */
  public StandardDialog(Component parent, boolean modal, JComponent content, String title) {
    super(JOptionPane.getFrameForComponent(parent), title, modal);
    initComponents();
    initSize(content);
    setTitle(title);
    setIconImages(Icons.getOpenTCSIcons());
  }

  /**
   * Initialises the size of the dialog based on the content.
   *
   * @param content the dialog to base the size on.
   */
  protected final void initSize(JComponent content) {
    fContent = content;
    getContentPane().add(content, BorderLayout.CENTER);
    content.setBorder(new EmptyBorder(new Insets(3, 3, 3, 3)));
    getRootPane().setDefaultButton(okButton);
    pack();
  }

  /**
   * Returns the content of this dialog.
   *
   * @return the content of this dialog.
   */
  public JComponent getContent() {
    return fContent;
  }

  /**
   * Return the return status of this dialog - one of RET_OK or RET_CANCEL.
   *
   * @return the return status of this dialog - one of RET_OK or RET_CANCEL.
   */
  public int getReturnStatus() {
    return returnStatus;
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    buttonPanel = new javax.swing.JPanel();
    okButton = new javax.swing.JButton();
    cancelButton = new CancelButton();

    addWindowListener(new java.awt.event.WindowAdapter() {
      public void windowClosing(java.awt.event.WindowEvent evt) {
        closeDialog(evt);
      }
    });

    okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() | java.awt.Font.BOLD));
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/system"); // NOI18N
    okButton.setText(bundle.getString("standardDialog.button_ok.text")); // NOI18N
    okButton.setOpaque(false);
    okButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        okButtonActionPerformed(evt);
      }
    });
    buttonPanel.add(okButton);

    cancelButton.setFont(cancelButton.getFont());
    cancelButton.setText(bundle.getString("standardDialog.button_cancel.text")); // NOI18N
    cancelButton.setOpaque(false);
    cancelButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        cancelButtonActionPerformed(evt);
      }
    });
    buttonPanel.add(cancelButton);

    getContentPane().add(buttonPanel, java.awt.BorderLayout.SOUTH);

    pack();
  }// </editor-fold>//GEN-END:initComponents
  // CHECKSTYLE:ON

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
      doClose(RET_OK);
    }//GEN-LAST:event_okButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
      doClose(RET_CANCEL);
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog
      doClose(RET_CANCEL);
    }//GEN-LAST:event_closeDialog

  /**
   * Closes the dialog.
   */
  private void doClose(int retStatus) {
    returnStatus = retStatus;
    setVisible(false);
    dispose();
  }

  // CHECKSTYLE:OFF
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel buttonPanel;
  private javax.swing.JButton cancelButton;
  private javax.swing.JButton okButton;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/phase/AssignFreePeripheralsPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching.phase;

import java.util.Collection;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralControllerPool;
import org.opentcs.strategies.basic.peripherals.dispatching.JobSelectionStrategy;
import org.opentcs.strategies.basic.peripherals.dispatching.PeripheralDispatcherPhase;
import org.opentcs.strategies.basic.peripherals.dispatching.PeripheralJobUtil;
import org.opentcs.util.ExplainedBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Assigns peripheral jobs to peripheral devices that are currently not processing any and are
 * not reserved for any reservation token.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignFreePeripheralsPhase
    implements PeripheralDispatcherPhase {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AssignFreePeripheralsPhase.class);
  /**
   * The object service.
   */
  private final TCSObjectService objectService;
  /**
   * The strategy to use for selecting jobs for peripheral devices.
   */
  private final JobSelectionStrategy jobSelectionStrategy;
  /**
   * The peripheral controller pool.
   */
  private final PeripheralControllerPool peripheralControllerPool;
  /**
   * Provides service functions for working with peripheral jobs and their states.
   */
  private final PeripheralJobUtil peripheralJobUtil;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public AssignFreePeripheralsPhase(TCSObjectService objectService,
                                    JobSelectionStrategy jobSelectionStrategy,
                                    PeripheralControllerPool peripheralControllerPool,
                                    PeripheralJobUtil peripheralJobUtil) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.jobSelectionStrategy = requireNonNull(jobSelectionStrategy, "jobSelectionStrategy");
    this.peripheralControllerPool = requireNonNull(peripheralControllerPool,
                                                   "peripheralControllerPool");
    this.peripheralJobUtil = requireNonNull(peripheralJobUtil, "peripheralJobUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    Set<Location> availablePeripherals = objectService.fetchObjects(Location.class,
                                                                    this::availableForAnyJob);
    if (availablePeripherals.isEmpty()) {
      LOG.debug("No peripherals available, skipping potentially expensive fetching of jobs.");
      return;
    }
    Set<PeripheralJob> jobsToBeProcessed = objectService.fetchObjects(PeripheralJob.class,
                                                                      this::toBeProcessed);
    LOG.debug("Available for dispatching: {} peripheral jobs and {} peripheral devices.",
              jobsToBeProcessed.size(),
              availablePeripherals.size());

    for (Location location : availablePeripherals) {
      tryAssignJob(location, jobsToBeProcessed);
    }
  }

  private boolean availableForAnyJob(Location location) {
    return processesNoJob(location) && !hasReservationToken(location);
  }

  private boolean processesNoJob(Location location) {
    return location.getPeripheralInformation().getProcState()
        == PeripheralInformation.ProcState.IDLE
        && location.getPeripheralInformation().getState()
        == PeripheralInformation.State.IDLE;
  }

  private boolean hasReservationToken(Location location) {
    return location.getPeripheralInformation().getReservationToken() != null;
  }

  private boolean toBeProcessed(PeripheralJob job) {
    return job.getState() == PeripheralJob.State.TO_BE_PROCESSED;
  }

  private void tryAssignJob(Location location, Collection<PeripheralJob> availableJobs) {
    LOG.debug("Trying to find job for peripheral '{}'...", location.getName());
    Optional<PeripheralJob> selectedJob = jobSelectionStrategy.select(
        availableJobs.stream()
            .filter(job -> matchesLocation(job, location))
            .collect(Collectors.toList()),
        location
    );
    if (selectedJob.isEmpty()) {
      return;
    }

    ExplainedBoolean canProcess = canProcess(location, selectedJob.get());
    if (!canProcess.getValue()) {
      LOG.debug("{} cannot process peripheral job {}: {}",
                location.getName(),
                selectedJob.get().getName(),
                canProcess.getReason());
      return;
    }

    assignJob(selectedJob.get(), location);
  }

  private boolean matchesLocation(PeripheralJob job, Location location) {
    return Objects.equals(job.getPeripheralOperation().getLocation(),
                          location.getReference());
  }

  private ExplainedBoolean canProcess(Location location, PeripheralJob job) {
    return peripheralControllerPool
        .getPeripheralController(location.getReference()).canProcess(job);
  }

  private void assignJob(PeripheralJob job, Location location) {
    LOG.debug("Assigning job '{}' to peripheral '{}'...", job.getName(), location.getName());
    peripheralJobUtil.assignPeripheralJob(location, job);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/ServiceUnavailableException.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;

/**
 * Thrown when a (remote) service is not available for processing a request.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ServiceUnavailableException
    extends KernelRuntimeException {

  /**
   * Creates a new ServiceUnavailableException with the given detail message.
   *
   * @param message The detail message.
   */
  public ServiceUnavailableException(String message) {
    super(message);
  }

  /**
   * Creates a new ServiceUnavailableException with the given detail message and cause.
   *
   * @param message The detail message.
   * @param cause The cause.
   */
  public ServiceUnavailableException(String message, Throwable cause) {
    super(message, cause);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/LayerGroup.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model.visualization;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;

/**
 * Describes a layer group in a plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerGroup
    implements Serializable {

  /**
   * The unique ID of this layer group.
   */
  private final int id;
  /**
   * The name of this layer group.
   */
  private final String name;
  /**
   * Whether this layer group is visible or not.
   */
  private final boolean visible;

  /**
   * Creates a new instance.
   *
   * @param id The unique ID of the layer group.
   * @param name The name of the layer group.
   * @param visible Whether the layer group is visible or not.
   */
  public LayerGroup(int id, String name, boolean visible) {
    this.id = id;
    this.name = requireNonNull(name, "name");
    this.visible = visible;
  }

  /**
   * Returns the unique ID of this layer group.
   *
   * @return The unique Id of this layer group.
   */
  public int getId() {
    return id;
  }

  /**
   * Returns whether this layer group is visible or not.
   *
   * @return Whether this layer group is visible or not.
   */
  public boolean isVisible() {
    return visible;
  }

  /**
   * Creates a copy of this object, with the given visible state.
   *
   * @param visible The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LayerGroup withVisible(boolean visible) {
    return new LayerGroup(id, name, visible);
  }

  /**
   * Returns the name of this layer group.
   *
   * @return The name of this layer group.
   */
  public String getName() {
    return name;
  }

  /**
   * Creates a copy of this object, with the given name.
   *
   * @param name The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LayerGroup withName(String name) {
    return new LayerGroup(id, name, visible);
  }

  @Override
  public String toString() {
    return "LayerGroup{" + ""
        + "id=" + id + ", "
        + "name=" + name + ", "
        + "visible=" + visible + '}';
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/parking/ParkingPositionPriorityComparatorTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import org.junit.*;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.data.model.Point;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ParkingPositionPriorityComparatorTest {

  private ParkingPositionPriorityComparator comparator;

  @Before
  public void setUp() {
    comparator = new ParkingPositionPriorityComparator(new ParkingPositionToPriorityFunction());
  }

  @Test
  public void prefersPrioritizedParkingPositions() {
    Point pointWithoutPrio
        = new Point("Point without prio")
            .withType(Point.Type.PARK_POSITION);
    Point pointWithPrio
        = new Point("Point with prio")
            .withType(Point.Type.PARK_POSITION)
            .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "1");

    // Let's try it the one way, ...
    assertThat(comparator.compare(pointWithPrio, pointWithoutPrio),
               lessThan(0));
    // ...and the other way.
    assertThat(comparator.compare(pointWithoutPrio, pointWithPrio),
               greaterThan(0));
  }

  @Test
  public void prefersSmallerPriorityIntegers() {
    Point pointWithLowerPrioValue
        = new Point("Point with lower prio value")
            .withType(Point.Type.PARK_POSITION)
            .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "23");
    Point pointWithHigherPrioValue
        = new Point("Point with higher prio value")
            .withType(Point.Type.PARK_POSITION)
            .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "142");

    // Let's try it the one way, ...
    assertThat(comparator.compare(pointWithLowerPrioValue, pointWithHigherPrioValue),
               lessThan(0));
    // ...and the other way.
    assertThat(comparator.compare(pointWithHigherPrioValue, pointWithLowerPrioValue),
               greaterThan(0));
  }

  @Test
  public void treatsSamePrioritiesEqually() {
    Point point1
        = new Point("Point 1, with prio 4")
            .withType(Point.Type.PARK_POSITION)
            .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "4");
    Point point2
        = new Point("Point 2, also with prio 4")
            .withType(Point.Type.PARK_POSITION)
            .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "4");

    // Let's try it the one way, ...
    assertThat(comparator.compare(point1, point2),
               is(0));
    // ...and the other way.
    assertThat(comparator.compare(point2, point1),
               is(0));
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/menus/MenuFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus;

import java.util.Collection;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * A factory for various menus and menu items.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface MenuFactory {

  /**
   * Creates a popup menu with actions for a set of vehicles.
   *
   * @param vehicles The vehicle models for which to create the popup menu.
   * @return A popup menu with actions for the given vehicle.
   */
  VehiclePopupMenu createVehiclePopupMenu(Collection<VehicleModel> vehicles);
}


<|start_filename|>openTCS-Common/src/test/java/org/opentcs/util/gui/StringTableCellRendererTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.gui;

import java.awt.Component;
import javax.swing.JLabel;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import org.junit.*;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StringTableCellRendererTest {

  private StringTableCellRenderer<TCSObjectReference<?>> renderer;

  @Before
  public void setUp() {
    renderer = new StringTableCellRenderer<>(x -> x == null ? "" : x.getName());
  }

  @Test
  public void returnsNullForNullValue() {
    Component result = renderer.getTableCellRendererComponent(null, null, false, false, 0, 0);
    assertThat(result, is(instanceOf(JLabel.class)));
    JLabel labelResult = (JLabel) result;
    assertThat(labelResult.getText(), is(equalTo("")));
  }

  @Test
  public void returnsLabelWithNameAsText() {
    Vehicle vehicle = new Vehicle("VehicleName");
    TCSObjectReference<Vehicle> vehicleReference = vehicle.getReference();
    Component result = renderer.getTableCellRendererComponent(null, vehicleReference, false, false, 0, 0);
    assertThat(result, is(instanceOf(JLabel.class)));
    JLabel labelResult = (JLabel) result;
    assertThat(labelResult.getText(), is(equalTo("VehicleName")));
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/InternalPeripheralJobService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * Declares the methods the peripheral job service must provide which are not accessible to remote
 * peers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface InternalPeripheralJobService
    extends PeripheralJobService {

  /**
   * Updates a peripheral job's state.
   * Note that peripheral job states are intended to be manipulated by the peripheral job
   * dispatcher only.
   * Calling this method from any other parts of the kernel may result in undefined behaviour.
   *
   * @param ref A reference to the peripheral job to be modified.
   * @param state The peripheral job's new state.
   * @throws ObjectUnknownException If the referenced peripheral job does not exist.
   */
  void updatePeripheralJobState(TCSObjectReference<PeripheralJob> ref, PeripheralJob.State state)
      throws ObjectUnknownException;
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralControllerPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;

/**
 * Maintains associations between locations and peripheral controllers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralControllerPool {

  /**
   * Returns the peripheral controller associated with the given location.
   *
   * @param location The reference to the location.
   * @return The peripheral controller associated with the given location.
   * @throws IllegalArgumentException If no peripheral controller is associated with the given
   * location or if the referenced location does not exist.
   */
  @Nonnull
  PeripheralController getPeripheralController(TCSResourceReference<Location> location)
      throws IllegalArgumentException;
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/gui/Icons.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.gui;

import java.awt.Image;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Static methods related to window icons.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class Icons {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(Icons.class);
  /**
   * Path to the openTCS window icons.
   */
  private static final String ICON_PATH = "/org/opentcs/util/gui/res/icons/";
  /**
   * File names of the openTCS window icons.
   */
  private static final String[] ICON_FILES = {"opentcs_icon_016.png",
                                              "opentcs_icon_032.png",
                                              "opentcs_icon_064.png",
                                              "opentcs_icon_128.png",
                                              "opentcs_icon_256.png"};

  /**
   * Prevents instantiation.
   */
  private Icons() {
    // Do nada.
  }

  /**
   * Get the icon for OpenTCS windows in different resolutions.
   *
   * @return List of icons
   */
  public static List<Image> getOpenTCSIcons() {
    try {
      List<Image> icons = new LinkedList<>();
      for (String iconFile : ICON_FILES) {
        String iconURL = ICON_PATH + iconFile;
        final Image icon = ImageIO.read(Icons.class.getResource(iconURL));
        icons.add(icon);
      }
      return icons;
    }
    catch (IOException | IllegalArgumentException exc) {
      LOG.warn("Couldn't load icon images from path {}", ICON_PATH, exc);
      return new LinkedList<>();
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/scheduling/DummyScheduler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.scheduling;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.data.model.TCSResource;

/**
 * A <code>Scheduler</code> implementation that does not really do any resource management - all
 * allocations are granted immediately without checking.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DummyScheduler
    implements Scheduler {

  /**
   * Executes our <code>CallbackTask</code>s.
   */
  private ExecutorService callbackExecutor;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  /**
   * Creates a new DummyScheduler.
   */
  public DummyScheduler() {
  }

  @Override
  public void initialize() {
    callbackExecutor = Executors.newSingleThreadExecutor();
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    callbackExecutor.shutdown();
    initialized = false;
  }

  @Override
  public void claim(Client client, List<Set<TCSResource<?>>> resourceSequence) {
  }

  @Override
  public void allocate(Client resourceUser, Set<TCSResource<?>> resources) {
    requireNonNull(resourceUser, "resourceUser");
    requireNonNull(resources, "resources");
    // Just schedule the callback for successful allocation.
    callbackExecutor.execute(new CallbackTask(resourceUser, resources));
    // Don't do anything else - this is a dummy, after all.
  }

  @Override
  public void free(Client resourceUser, Set<TCSResource<?>> resources) {
  }

  @Override
  public void freeAll(Client client) {
  }

  @Override
  public void allocateNow(Client resourceUser, Set<TCSResource<?>> resources) {
  }

  @Override
  public void reschedule() {
  }

  @Override
  public void preparationSuccessful(Module module, Client client, Set<TCSResource<?>> resources) {
  }

  @Override
  public Map<String, Set<TCSResource<?>>> getAllocations() {
    return new HashMap<>();
  }

  /**
   * A task that merely calls back <code>ResourceUser</code>s.
   */
  private static class CallbackTask
      implements Runnable {

    /**
     * The client to call back.
     */
    private final Client client;
    /**
     * The resources the client is asking for.
     */
    private final Set<TCSResource<?>> resources;

    /**
     * Creates a new CallbackTask.
     *
     * @param newClient The client to call back.
     * @param newResources The resources the client is asking for.
     */
    CallbackTask(Client newClient, Set<TCSResource<?>> newResources) {
      client = newClient;
      resources = newResources;
    }

    @Override
    public void run() {
      client.allocationSuccessful(resources);
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/toolbar/OpenTCSCreationTool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.toolbar;

import com.google.inject.assistedinject.Assisted;
import java.awt.event.MouseEvent;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JOptionPane;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.tool.CreationTool;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.drawing.figures.ModelBasedFigure;
import org.opentcs.guing.components.layer.ActiveLayerProvider;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * A custom tool used to create {@code PointFigure}s and {@code LocationFigure}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSCreationTool
    extends CreationTool {

  /**
   * The resource bundle to use.
   */
  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);
  /**
   * Provides the currently active layer.
   */
  private final ActiveLayerProvider activeLayerProvider;

  /**
   * Creates a new instance.
   *
   * @param activeLayerProvider Provides the currently active layer.
   * @param prototype The figure to be used as a prototype.
   */
  @Inject
  public OpenTCSCreationTool(ActiveLayerProvider activeLayerProvider,
                             @Assisted Figure prototype) {
    super(prototype);
    this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");
  }

  @Override
  public void mousePressed(MouseEvent evt) {
    if (!activeLayerProvider.getActiveLayer().getLayer().isVisible()
        || !activeLayerProvider.getActiveLayer().getLayerGroup().isVisible()) {
      JOptionPane.showMessageDialog(
          evt.getComponent(),
          BUNDLE.getString("openTcsCreationTool.optionPane_activeLayerNotVisible.message"),
          BUNDLE.getString("openTcsCreationTool.optionPane_activeLayerNotVisible.title"),
          JOptionPane.INFORMATION_MESSAGE
      );
      return;
    }

    super.mousePressed(evt);
  }

  @Override
  protected Figure createFigure() {
    Figure figure = super.createFigure();

    if (figure instanceof ModelBasedFigure) {
      ((ModelBasedFigure) figure).getModel()
          .getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
    }
    else if (figure instanceof LabeledFigure) {
      ((LabeledFigure) figure).getPresentationFigure().getModel()
          .getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
    }

    return figure;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/PropertySuggestions.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;

/**
 * Objects implementing this interface provide a set for suggested property keys and values each.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PropertySuggestions {

  /**
   * Returns suggested property keys.
   *
   * @return Suggested property keys.
   */
  @Nonnull
  Set<String> getKeySuggestions();

  /**
   * Returns suggested property values.
   *
   * @return Suggested property values.
   */
  @Nonnull
  Set<String> getValueSuggestions();

  /**
   * Returns suggested property values that are specified for the <Code>key</Code>.
   *
   * @param key A key suggestion for which value suggestions are requested.
   * @return A set of property value suggestions.
   */
  default Set<String> getValueSuggestionsFor(String key) {
    return new HashSet<>();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/annotations/ScheduledApiChange.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.annotations;

import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Marks an API detail (class, method, field) that is scheduled for an incompatible change.
 * <p>
 * <em>This annotation should not be used outside the source code of the openTCS project itself. It
 * should not be considered part of the public API.</em>
 * </p>
 * <p>
 * This annotation is intended to be used as a supplement for @Deprecated for two purposes:
 * </p>
 * <ol>
 * <li>For users of the openTCS API to gain knowledge about upcoming changes.</li>
 * <li>For openTCS developers to easily find pending changes during pre-release cleanups.</li>
 * </ol>
 *
 * @author <NAME> (Fraunhofer IML)
 */
@Target({CONSTRUCTOR, FIELD, METHOD, TYPE})
@Retention(RetentionPolicy.SOURCE)
@Documented
@Repeatable(ScheduledApiChanges.class)
public @interface ScheduledApiChange {

  /**
   * Returns the date or version at which the API is scheduled to be changed.
   *
   * @return The date or version at which the API is scheduled to be changed.
   */
  String when();

  /**
   * Returns optional details about the scheduled change.
   *
   * @return Optional details about the scheduled change.
   */
  String details() default "";
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/kernel/vehicles/PeripheralInteractionTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import java.util.Arrays;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import org.junit.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.Route;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.data.peripherals.PeripheralOperation.ExecutionTrigger;
import org.opentcs.drivers.vehicle.MovementCommand;

/**
 * Defines test cases for {@link PeripheralInteraction}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralInteractionTest {

  /**
   * The vehicle instance to use for the tests.
   */
  private static final Vehicle VEHICLE = new Vehicle("Vehicle-01");
  /**
   * The reservation token to use for the tests.
   */
  private static final String RESERVATION_TOKEN = "SomeToken";
  /**
   * A (mocked) peripheral job service.
   */
  private PeripheralJobService peripheralJobService;
  /**
   * A (mocked) callback to be executed when interactions succeeded.
   */
  private Runnable succeededCallback;
  /**
   * A (mocked) callback to be executed when interactions failed.
   */
  private Runnable failedCallback;
  /**
   * The instance to test.
   */
  private PeripheralInteraction peripheralInteraction;

  public PeripheralInteractionTest() {
  }

  @Before
  public void setUp() {
    peripheralJobService = mock(PeripheralJobService.class);
    succeededCallback = mock(Runnable.class);
    failedCallback = mock(Runnable.class);
  }

  @Test
  public void shouldNotWaitForOperationCompletion() {
    PeripheralOperation operation = new PeripheralOperation(createLocation().getReference(),
                                                            RESERVATION_TOKEN,
                                                            ExecutionTrigger.BEFORE_MOVEMENT,
                                                            false);

    peripheralInteraction = new PeripheralInteraction(VEHICLE.getReference(),
                                                      new DummyMovementCommand(),
                                                      Arrays.asList(operation),
                                                      peripheralJobService,
                                                      RESERVATION_TOKEN);

    verify(succeededCallback, times(0)).run();
    assertThat(peripheralInteraction.hasState(PeripheralInteraction.State.PRISTINE), is(true));

    peripheralInteraction.start(succeededCallback, failedCallback);
    verify(peripheralJobService, times(1)).createPeripheralJob(any());
    verify(succeededCallback, times(1)).run();
    assertThat(peripheralInteraction.isFinished(), is(true));

    verify(succeededCallback, times(1)).run();
    verify(failedCallback, times(0)).run();
  }

  @Test
  public void shouldWaitForOperationCompletion() {
    PeripheralOperation operation = new PeripheralOperation(createLocation().getReference(),
                                                            RESERVATION_TOKEN,
                                                            ExecutionTrigger.BEFORE_MOVEMENT,
                                                            true);

    PeripheralJob peripheralJob = new PeripheralJob("SomeJob", RESERVATION_TOKEN, operation);
    when(peripheralJobService.createPeripheralJob(any())).thenReturn(peripheralJob);

    peripheralInteraction = new PeripheralInteraction(VEHICLE.getReference(),
                                                      new DummyMovementCommand(),
                                                      Arrays.asList(operation),
                                                      peripheralJobService,
                                                      RESERVATION_TOKEN);

    verify(succeededCallback, times(0)).run();
    assertThat(peripheralInteraction.hasState(PeripheralInteraction.State.PRISTINE), is(true));

    peripheralInteraction.start(succeededCallback, failedCallback);
    verify(peripheralJobService, times(1)).createPeripheralJob(any());
    verify(succeededCallback, times(0)).run();
    assertThat(peripheralInteraction.isFinished(), is(false));

    peripheralInteraction.onPeripheralJobFinished(peripheralJob);
    verify(succeededCallback, times(1)).run();
    assertThat(peripheralInteraction.isFinished(), is(true));

    verify(failedCallback, times(0)).run();
  }

  @Test
  public void shouldCallbackOnFailedRequiredInteraction() {
    PeripheralOperation operation = new PeripheralOperation(createLocation().getReference(),
                                                            RESERVATION_TOKEN,
                                                            ExecutionTrigger.BEFORE_MOVEMENT,
                                                            true);

    PeripheralJob peripheralJob = new PeripheralJob("SomeJob", RESERVATION_TOKEN, operation);
    when(peripheralJobService.createPeripheralJob(any())).thenReturn(peripheralJob);

    peripheralInteraction = new PeripheralInteraction(VEHICLE.getReference(),
                                                      new DummyMovementCommand(),
                                                      Arrays.asList(operation),
                                                      peripheralJobService,
                                                      RESERVATION_TOKEN);

    verify(succeededCallback, times(0)).run();
    assertThat(peripheralInteraction.hasState(PeripheralInteraction.State.PRISTINE), is(true));

    peripheralInteraction.start(succeededCallback, failedCallback);
    verify(peripheralJobService, times(1)).createPeripheralJob(any());
    verify(failedCallback, times(0)).run();
    assertThat(peripheralInteraction.isFailed(), is(false));

    peripheralInteraction.onPeripheralJobFailed(peripheralJob);
    verify(failedCallback, times(1)).run();
    assertThat(peripheralInteraction.isFailed(), is(true));

    verify(succeededCallback, times(0)).run();
  }

  private Location createLocation() {
    LocationType locationType = new LocationType("LocationType-01");
    return new Location("Location-01", locationType.getReference());
  }

  private class DummyMovementCommand
      implements MovementCommand {

    private final Route.Step dummyStep;

    public DummyMovementCommand() {
      Point srcPoint = new Point("Point-01");
      Point destPoint = new Point("Point-02");
      Path path = new Path("Point-01 --- Point-02",
                           srcPoint.getReference(),
                           destPoint.getReference());
      dummyStep = new Route.Step(path, srcPoint, destPoint, Vehicle.Orientation.FORWARD, 0);
    }

    @Override
    public Route getRoute() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Route.Step getStep() {
      return dummyStep;
    }

    @Override
    public String getOperation() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isWithoutOperation() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Location getOpLocation() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public boolean isFinalMovement() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Point getFinalDestination() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Location getFinalDestinationLocation() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getFinalOperation() {
      throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public Map<String, String> getProperties() {
      throw new UnsupportedOperationException("Not supported yet.");
    }
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralCommAdapterPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import com.google.inject.assistedinject.Assisted;
import java.awt.event.ItemEvent;
import java.util.Arrays;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.DefaultComboBoxModel;
import javax.swing.SwingUtilities;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.commadapter.peripheral.loopback.commands.EnableManualModeCommand;
import org.opentcs.commadapter.peripheral.loopback.commands.FinishJobProcessingCommand;
import org.opentcs.commadapter.peripheral.loopback.commands.SetPeripheralPausedCommand;
import org.opentcs.commadapter.peripheral.loopback.commands.SetStateCommand;
import org.opentcs.customizations.ServiceCallWrapper;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanel;
import org.opentcs.util.CallWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The panel for the loopback peripheral communication adapter.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralCommAdapterPanel
    extends PeripheralCommAdapterPanel {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LoopbackPeripheralCommAdapterPanel.class);
  /**
   * The service portal to use.
   */
  private final KernelServicePortal servicePortal;
  /**
   * The call wrapper to use for service calls.
   */
  private final CallWrapper callWrapper;
  /**
   * The comm adapter's process model.
   */
  private LoopbackPeripheralProcessModel processModel;

  @Inject
  public LoopbackPeripheralCommAdapterPanel(@Assisted LoopbackPeripheralProcessModel processModel,
                                            KernelServicePortal servicePortal,
                                            @ServiceCallWrapper CallWrapper callWrapper) {
    this.processModel = requireNonNull(processModel, "processModel");
    this.servicePortal = requireNonNull(servicePortal, "servicePortal");
    this.callWrapper = requireNonNull(callWrapper, "callWrapper");

    initComponents();
    updateComponentsEnabled();
    updateComponentContents();
  }

  @Override
  public void processModelChanged(PeripheralProcessModel processModel) {
    requireNonNull(processModel, "processModel");
    if (!(processModel instanceof LoopbackPeripheralProcessModel)) {
      return;
    }

    SwingUtilities.invokeLater(() -> {
      this.processModel = (LoopbackPeripheralProcessModel) processModel;
      updateComponentsEnabled();
      updateComponentContents();
    });
  }

  private void updateComponentsEnabled() {
    boolean enabled = processModel.isCommAdapterEnabled();
    stateComboBox.setEnabled(enabled);
    pausePeripheralCheckBox.setEnabled(enabled);
    finishCurrentJobButton.setEnabled(processModel.isManualModeEnabled());
    failCurrentJobButton.setEnabled(processModel.isManualModeEnabled());
  }

  private void updateComponentContents() {
    stateComboBox.setSelectedItem(processModel.getState());
    pausePeripheralCheckBox.setSelected(processModel.isPeripheralPaused());
    manualModeRadioButton.setSelected(processModel.isManualModeEnabled());
    automaticModeRadioButton.setSelected(!processModel.isManualModeEnabled());
  }

  private void sendCommAdapterCommand(PeripheralAdapterCommand command) {
    try {
      callWrapper.call(() -> servicePortal.getPeripheralService()
          .sendCommAdapterCommand(processModel.getLocation(), command));
    }
    catch (Exception ex) {
      LOG.warn("Error sending comm adapter command '{}'", command, ex);
    }
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always regenerated
   * by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    statePanel = new javax.swing.JPanel();
    pausePeripheralLabel = new javax.swing.JLabel();
    pausePeripheralCheckBox = new javax.swing.JCheckBox();
    stateLabel = new javax.swing.JLabel();
    stateComboBox = new javax.swing.JComboBox<>();
    jobProcessingPanel = new javax.swing.JPanel();
    automaticModeRadioButton = new javax.swing.JRadioButton();
    manualModeRadioButton = new javax.swing.JRadioButton();
    finishCurrentJobButton = new javax.swing.JButton();
    failCurrentJobButton = new javax.swing.JButton();

    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/commadapter/peripheral/loopback/Bundle"); // NOI18N
    statePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("loopbackPeripheralCommAdapterPanel.panel_state.border.title"))); // NOI18N
    statePanel.setName("statePanel"); // NOI18N
    statePanel.setLayout(new java.awt.GridBagLayout());

    pausePeripheralLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
    pausePeripheralLabel.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.label_pausePeripheral.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 0);
    statePanel.add(pausePeripheralLabel, gridBagConstraints);

    pausePeripheralCheckBox.setEnabled(false);
    pausePeripheralCheckBox.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
    pausePeripheralCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING);
    pausePeripheralCheckBox.setName("pausePeripheralCheckBox"); // NOI18N
    pausePeripheralCheckBox.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        pausePeripheralCheckBoxActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    statePanel.add(pausePeripheralCheckBox, gridBagConstraints);

    stateLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
    stateLabel.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.label_state.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 0);
    statePanel.add(stateLabel, gridBagConstraints);

    stateComboBox.setModel(new DefaultComboBoxModel<>(Arrays.asList(PeripheralInformation.State.values()).stream().filter(state -> state != PeripheralInformation.State.NO_PERIPHERAL).toArray(PeripheralInformation.State[]::new)));
    stateComboBox.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        stateComboBoxItemStateChanged(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    statePanel.add(stateComboBox, gridBagConstraints);

    jobProcessingPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("loopbackPeripheralCommAdapterPanel.panel_jobProcessing.border.title"))); // NOI18N
    jobProcessingPanel.setLayout(new java.awt.GridBagLayout());

    automaticModeRadioButton.setSelected(true);
    automaticModeRadioButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingAutomatic.text")); // NOI18N
    automaticModeRadioButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
    automaticModeRadioButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
    automaticModeRadioButton.setName("automaticModeRadioButton"); // NOI18N
    automaticModeRadioButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        automaticModeRadioButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    jobProcessingPanel.add(automaticModeRadioButton, gridBagConstraints);

    manualModeRadioButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.radioButton_jobProcessingManual.text")); // NOI18N
    manualModeRadioButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
    manualModeRadioButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
    manualModeRadioButton.setName("manualModeRadioButton"); // NOI18N
    manualModeRadioButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        manualModeRadioButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 0);
    jobProcessingPanel.add(manualModeRadioButton, gridBagConstraints);

    finishCurrentJobButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.button_finishCurrentJob.text")); // NOI18N
    finishCurrentJobButton.setEnabled(false);
    finishCurrentJobButton.setName("finishCurrentJobButton"); // NOI18N
    finishCurrentJobButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        finishCurrentJobButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 3);
    jobProcessingPanel.add(finishCurrentJobButton, gridBagConstraints);

    failCurrentJobButton.setText(bundle.getString("loopbackPeripheralCommAdapterPanel.button_failCurrentJob.text")); // NOI18N
    failCurrentJobButton.setEnabled(false);
    failCurrentJobButton.setName("processCurrentJobButton"); // NOI18N
    failCurrentJobButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        failCurrentJobButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 3);
    jobProcessingPanel.add(failCurrentJobButton, gridBagConstraints);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
    this.setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
          .addComponent(statePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 194, Short.MAX_VALUE)
          .addComponent(jobProcessingPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        .addContainerGap(170, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(statePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jobProcessingPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap(140, Short.MAX_VALUE))
    );

    getAccessibleContext().setAccessibleName(bundle.getString("loopbackPeripheralCommAdapterPanel.accessibleName")); // NOI18N
  }// </editor-fold>//GEN-END:initComponents

  private void manualModeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manualModeRadioButtonActionPerformed
    sendCommAdapterCommand(new EnableManualModeCommand(manualModeRadioButton.isSelected()));
  }//GEN-LAST:event_manualModeRadioButtonActionPerformed

  private void automaticModeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_automaticModeRadioButtonActionPerformed
    sendCommAdapterCommand(new EnableManualModeCommand(!manualModeRadioButton.isSelected()));
  }//GEN-LAST:event_automaticModeRadioButtonActionPerformed

  private void finishCurrentJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_finishCurrentJobButtonActionPerformed
    sendCommAdapterCommand(new FinishJobProcessingCommand(false));
  }//GEN-LAST:event_finishCurrentJobButtonActionPerformed

  private void pausePeripheralCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pausePeripheralCheckBoxActionPerformed
    sendCommAdapterCommand(new SetPeripheralPausedCommand(pausePeripheralCheckBox.isSelected()));
  }//GEN-LAST:event_pausePeripheralCheckBoxActionPerformed

  private void stateComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_stateComboBoxItemStateChanged
    if (evt.getStateChange() != ItemEvent.SELECTED) {
      return;
    }

    PeripheralInformation.State selectedState
        = (PeripheralInformation.State) stateComboBox.getSelectedItem();
    if (selectedState == processModel.getState()) {
      // If the selection has changed due to an update in the process model (i.e. the user has not
      // selected an item in this panel's combo box), we don't want to send a set state command.
      return;
    }

    sendCommAdapterCommand(
        new SetStateCommand((PeripheralInformation.State) stateComboBox.getSelectedItem())
    );
  }//GEN-LAST:event_stateComboBoxItemStateChanged

  private void failCurrentJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_failCurrentJobButtonActionPerformed
    sendCommAdapterCommand(new FinishJobProcessingCommand(true));
  }//GEN-LAST:event_failCurrentJobButtonActionPerformed

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JRadioButton automaticModeRadioButton;
  private javax.swing.JButton failCurrentJobButton;
  private javax.swing.JButton finishCurrentJobButton;
  private javax.swing.JPanel jobProcessingPanel;
  private javax.swing.JRadioButton manualModeRadioButton;
  private javax.swing.JCheckBox pausePeripheralCheckBox;
  private javax.swing.JLabel pausePeripheralLabel;
  private javax.swing.JComboBox<PeripheralInformation.State> stateComboBox;
  private javax.swing.JLabel stateLabel;
  private javax.swing.JPanel statePanel;
  // End of variables declaration//GEN-END:variables
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/DrawnModelComponent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import org.opentcs.guing.components.properties.type.LayerWrapperProperty;

/**
 * A model component that is drawn and represented by a corresponding figure.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface DrawnModelComponent
    extends ModelComponent {

  /**
   * The property key for the layer wrapper that contains the layer on which a model component 
   * (respectively its figure) is to be drawn.
   */
  String LAYER_WRAPPER = "LAYER_WRAPPER";

  /**
   * Returns this component's layer wrapper property.
   *
   * @return This component's layer wrapper property.
   */
  default LayerWrapperProperty getPropertyLayerWrapper() {
    return (LayerWrapperProperty) getProperty(LAYER_WRAPPER);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/components/drawing/DrawingInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import javax.inject.Singleton;
import org.jhotdraw.draw.DrawingEditor;
import org.opentcs.guing.components.drawing.figures.VehicleFigureFactory;
import org.opentcs.guing.util.CourseObjectFactory;
import org.opentcs.guing.util.VehicleCourseObjectFactory;
import org.opentcs.thirdparty.components.drawing.OpenTCSDrawingViewOperating;

/**
 * A Guice module for this package.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DrawingInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {
    install(new FactoryModuleBuilder().build(VehicleFigureFactory.class));
    bind(CourseObjectFactory.class).to(VehicleCourseObjectFactory.class);

    bind(OpenTCSDrawingEditorOperating.class).in(Singleton.class);
    bind(OpenTCSDrawingEditor.class).to(OpenTCSDrawingEditorOperating.class);
    bind(DrawingEditor.class).to(OpenTCSDrawingEditorOperating.class);

    bind(OpenTCSDrawingView.class).to(OpenTCSDrawingViewOperating.class);

    bind(DrawingOptions.class).in(Singleton.class);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/InternalTransportOrderService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import java.util.List;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;

/**
 * Declares the methods the transport order service must provide which are not accessible to remote
 * peers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface InternalTransportOrderService
    extends TransportOrderService {

  /**
   * Sets an order sequence's finished flag.
   *
   * @param ref A reference to the order sequence to be modified.
   * @throws ObjectUnknownException If the referenced transport order is not in this pool.
   */
  void markOrderSequenceFinished(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException;

  /**
   * Updates an order sequence's finished index.
   *
   * @param ref A reference to the order sequence to be modified.
   * @param index The sequence's new finished index.
   * @throws ObjectUnknownException If the referenced transport order is not in this pool.
   */
  void updateOrderSequenceFinishedIndex(TCSObjectReference<OrderSequence> ref, int index)
      throws ObjectUnknownException;

  /**
   * Updates an order sequence's processing vehicle.
   *
   * @param seqRef A reference to the order sequence to be modified.
   * @param vehicleRef A reference to the vehicle processing the order sequence.
   * @throws ObjectUnknownException If the referenced transport order is not in this pool.
   */
  void updateOrderSequenceProcessingVehicle(TCSObjectReference<OrderSequence> seqRef,
                                            TCSObjectReference<Vehicle> vehicleRef)
      throws ObjectUnknownException;

  /**
   * Updates a transport order's list of drive orders.
   *
   * @param ref A reference to the transport order to be modified.
   * @param driveOrders The drive orders containing the data to be copied into this transport
   * order's drive orders.
   * @throws ObjectUnknownException If the referenced transport order does not exist.
   */
  void updateTransportOrderDriveOrders(TCSObjectReference<TransportOrder> ref,
                                       List<DriveOrder> driveOrders)
      throws ObjectUnknownException;

  /**
   * Updates a transport order's current drive order.
   * Marks the current drive order as finished, adds it to the list of past drive orders and sets
   * the current drive order to the next one of the list of future drive orders (or {@code null},
   * if that list is empty).
   * If the current drive order is {@code null} because all drive orders have been finished
   * already or none has been started, yet, nothing happens.
   *
   * @param ref A reference to the transport order to be modified.
   * @throws ObjectUnknownException If the referenced transport order is not in this pool.
   */
  void updateTransportOrderNextDriveOrder(TCSObjectReference<TransportOrder> ref)
      throws ObjectUnknownException;

  /**
   * Updates a transport order's processing vehicle.
   *
   * @param orderRef A reference to the transport order to be modified.
   * @param vehicleRef A reference to the vehicle processing the order.
   * @param driveOrders The drive orders containing the data to be copied into this transport
   * order's drive orders.
   * @throws ObjectUnknownException If the referenced transport order does not exist.
   * @throws IllegalArgumentException If the destinations of the given drive orders do not match
   * the destinations of the drive orders in this transport order.
   */
  void updateTransportOrderProcessingVehicle(TCSObjectReference<TransportOrder> orderRef,
                                             TCSObjectReference<Vehicle> vehicleRef,
                                             List<DriveOrder> driveOrders)
      throws ObjectUnknownException, IllegalArgumentException;

  /**
   * Updates a transport order's state.
   * Note that transport order states are intended to be manipulated by the dispatcher only.
   * Calling this method from any other parts of the kernel may result in undefined behaviour.
   *
   * @param ref A reference to the transport order to be modified.
   * @param state The transport order's new state.
   * @throws ObjectUnknownException If the referenced transport order does not exist.
   */
  void updateTransportOrderState(TCSObjectReference<TransportOrder> ref,
                                 TransportOrder.State state)
      throws ObjectUnknownException;
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/CompositeVehicleComparatorTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.mockito.Mockito;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeVehicleComparator;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorIdleFirst;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeVehicleComparatorTest {

  private CompositeVehicleComparator comparator;
  private DefaultDispatcherConfiguration configuration;
  private Map<String, Comparator<Vehicle>> availableComparators;

  @Before
  public void setUp() {
    configuration = Mockito.mock(DefaultDispatcherConfiguration.class);
    availableComparators = new HashMap<>();

  }

  @Test
  public void sortNamesUpForOtherwiseEqualInstances() {
    Mockito.when(configuration.vehiclePriorities())
        .thenReturn(new LinkedList<>());
    comparator = new CompositeVehicleComparator(configuration, availableComparators);

    Vehicle candidate1 = new Vehicle("AA");
    Vehicle candidate2 = new Vehicle("CC");
    Vehicle candidate3 = new Vehicle("AB");

    List<Vehicle> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate1)));
    assertThat(list.get(1), is(theInstance(candidate3)));
    assertThat(list.get(2), is(theInstance(candidate2)));
  }

  @Test
  public void sortsByNameAndEnergylevel() {
    Mockito.when(configuration.vehiclePriorities())
        .thenReturn(new LinkedList<>());
    comparator = new CompositeVehicleComparator(configuration, availableComparators);

    Vehicle candidate1 = new Vehicle("AA").withEnergyLevel(1);
    Vehicle candidate2 = new Vehicle("CC").withEnergyLevel(2);
    Vehicle candidate3 = new Vehicle("BB").withEnergyLevel(2);

    List<Vehicle> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate3)));
    assertThat(list.get(1), is(theInstance(candidate2)));
    assertThat(list.get(2), is(theInstance(candidate1)));
  }

  @Test
  public void sortsByNameEnergylevelRoutingCost() {

    Mockito.when(configuration.vehiclePriorities())
        .thenReturn(Arrays.asList("IDLE_FIRST"));
    availableComparators.put("IDLE_FIRST",
                             new VehicleComparatorIdleFirst());

    comparator = new CompositeVehicleComparator(configuration, availableComparators);

    Vehicle candidate1 = new Vehicle("AA").withEnergyLevel(30).withState(Vehicle.State.EXECUTING);
    Vehicle candidate2 = new Vehicle("BB").withEnergyLevel(30).withState(Vehicle.State.IDLE);
    Vehicle candidate3 = new Vehicle("CC").withEnergyLevel(60).withState(Vehicle.State.IDLE);
    Vehicle candidate4 = new Vehicle("DD").withEnergyLevel(60).withState(Vehicle.State.IDLE);

    List<Vehicle> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);
    list.add(candidate4);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate3)));
    assertThat(list.get(1), is(theInstance(candidate4)));
    assertThat(list.get(2), is(theInstance(candidate2)));
    assertThat(list.get(3), is(theInstance(candidate1)));
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/tree/elements/VehicleUserObjectModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import javax.inject.Inject;
import javax.swing.JPopupMenu;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;

/**
 * A Vehicle object in the tree view.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class VehicleUserObjectModeling
    extends VehicleUserObject {

  /**
   * Creates a new instance.
   *
   * @param model The corresponding vehicle object.
   * @param guiManager The gui manager.
   * @param modelManager Provides the current system model.
   */
  @Inject
  public VehicleUserObjectModeling(@Assisted VehicleModel model,
                                   GuiManager guiManager,
                                   ModelManager modelManager) {
    super(model, guiManager, modelManager);
  }

  @Override  // AbstractUserObject
  public JPopupMenu getPopupMenu() {
    return null;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/IntegerPropertyCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Component;
import java.text.ParseException;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JTable;
import javax.swing.JTextField;
import org.opentcs.guing.components.properties.type.IntegerProperty;
import org.opentcs.guing.util.UserMessageHelper;
import org.slf4j.LoggerFactory;

/**
 * A cell editor for an integer property.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class IntegerPropertyCellEditor
    extends AbstractPropertyCellEditor {

  /**
   * Creates a new instance of IntegerPropertyCellEditor
   *
   * @param textField
   * @param umh
   */
  public IntegerPropertyCellEditor(JFormattedTextField textField, UserMessageHelper umh) {
    super(textField, umh);
    setStyle(textField);
  }

  /**
   * Initialises the style for the text field.
   *
   * @param textField
   */
  protected final void setStyle(JTextField textField) {
    setClickCountToStart(1);
    textField.setHorizontalAlignment(JTextField.LEFT);
  }

  /**
   * Create the component for this editor.
   *
   * @return the component for this editor.
   */
  @Override
  protected JComponent createComponent() {
    return (JComponent) getComponent();
  }

  @Override
  public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {

    JFormattedTextField textField = (JFormattedTextField) getComponent();
    setValue(value);

    if (property().getValue() instanceof Integer) {
      textField.setValue(property().getValue());
    }

    return fComponent;
  }

  @Override
  public Object getCellEditorValue() {
    JFormattedTextField textField = (JFormattedTextField) getComponent();

    try {
      textField.commitEdit();
    }
    catch (ParseException ex) {
      LoggerFactory.getLogger(IntegerPropertyCellEditor.class).error("ParseException: {0}",
                                                                     textField.getText());
    }

    try {
      int newValue = Integer.parseInt(textField.getText());
      int oldValue = (int) property().getValue();
      property().setValue(newValue);

      if (newValue != oldValue) {
        markProperty();
      }

      return property();
    }
    catch (NumberFormatException e) {
      return property();
    }
    catch (ClassCastException ex) {
      markProperty();
      return property();
    }
  }

  /**
   * Returns the property for this editor.
   *
   * @return the property for this editor.
   */
  protected IntegerProperty property() {
    return (IntegerProperty) fProperty;
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/main/java/org/opentcs/guing/plugins/panels/statistics/PointStats.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.statistics;

/**
 * Statistics data for a point.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class PointStats
    extends Stats {

  /**
   * The total time the point was occupied by vehicles.
   */
  private long totalTimeOccupied;
  /**
   * When the point became occupied the last time.
   */
  private long lastOccupationStart;

  /**
   * Creates a new instance.
   *
   * @param name The name of the point.
   * @param totalRuntime The total runtime recorded.
   */
  public PointStats(final String name, final long totalRuntime) {
    super(name, totalRuntime);
  }

  /**
   * Returns the total time the point was occupied by vehicles.
   *
   * @return The total time the point was occupied by vehicles.
   */
  public long getTotalTimeOccupied() {
    return totalTimeOccupied;
  }

  /**
   * Indicates the point became occupied at the given point of time.
   *
   * @param timestamp When the point became occupied.
   */
  public void startOccupation(long timestamp) {
    assert timestamp > 0;
    lastOccupationStart = timestamp;
  }

  /**
   * Indicates the point became free at the given point of time.
   *
   * @param timestamp When the point became free.
   */
  public void stopOccupation(long timestamp) {
    assert timestamp > 0;
    if (lastOccupationStart != 0) {
      totalTimeOccupied += timestamp - lastOccupationStart;
    }
    lastOccupationStart = 0;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/messages/package-info.java<|end_filename|>
/**
 * Reference implementations of commonly used messages to be processed by vehicle drivers.
 */
package org.opentcs.drivers.vehicle.messages;


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/menubar/EditMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenu;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.ClearSelectionAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.CopyAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.CutAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.DeleteAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.DuplicateAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.PasteAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.SelectAllAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's "Edit" menu.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EditMenu
    extends JMenu {

//  private final JMenuItem menuItemCopy;
//  private final JMenuItem menuItemCut;
//  private final JMenuItem menuItemDuplicate;
//  private final JMenuItem menuItemPaste;
  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   */
  @Inject
  public EditMenu(ViewActionMap actionMap) {
    requireNonNull(actionMap, "actionMap");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);

    this.setText(labels.getString("editMenu.text"));
    this.setToolTipText(labels.getString("editMenu.tooltipText"));
    this.setMnemonic('E');

    // Undo, Redo
    add(actionMap.get(UndoRedoManager.UNDO_ACTION_ID));
    add(actionMap.get(UndoRedoManager.REDO_ACTION_ID));
    addSeparator();
    // Cut, Copy, Paste, Duplicate
//    menuItemCut = menuEdit.add(actionMap.get(CutAction.ID));
//    menuItemCopy = menuEdit.add(actionMap.get(CopyAction.ID));
//    menuItemPaste = menuEdit.add(actionMap.get(PasteAction.ID));
//    menuItemDuplicate = menuEdit.add(actionMap.get(DuplicateAction.ID));
    // Delete
    add(actionMap.get(DeleteAction.ID));
    add(actionMap.get(CopyAction.ID));
    add(actionMap.get(PasteAction.ID));
    add(actionMap.get(DuplicateAction.ID));
    add(actionMap.get(CutAction.ID));
    addSeparator();
    // Select all, Clear selection
    add(actionMap.get(SelectAllAction.ID));
    add(actionMap.get(ClearSelectionAction.ID));
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/phase/ReleasePeripheralsPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching.phase;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.data.model.Location;
import org.opentcs.strategies.basic.peripherals.dispatching.PeripheralDispatcherPhase;
import org.opentcs.strategies.basic.peripherals.dispatching.PeripheralReleaseStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Releases the reservations of peripherals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ReleasePeripheralsPhase
    implements PeripheralDispatcherPhase {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ReleasePeripheralsPhase.class);
  /**
   * The peripheral service.
   */
  private final InternalPeripheralService peripheralService;
  /**
   * The release strategy to use.
   */
  private final PeripheralReleaseStrategy releaseStrategy;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public ReleasePeripheralsPhase(InternalPeripheralService peripheralService,
                                 PeripheralReleaseStrategy releaseStrategy) {
    this.peripheralService = requireNonNull(peripheralService, "peripheralService");
    this.releaseStrategy = requireNonNull(releaseStrategy, "releaseStrategy");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    Collection<Location> peripheralsToBeRelease
        = releaseStrategy.selectPeripheralsToRelease(peripheralService.fetchObjects(Location.class));
    for (Location location : peripheralsToBeRelease) {
      releasePeripheral(location);
    }
  }

  private void releasePeripheral(Location location) {
    LOG.debug("Releasing peripheral '{}'...", location.getName());
    peripheralService.updatePeripheralReservationToken(location.getReference(), null);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/transport/OrderTypeSuggestionsModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import javax.inject.Singleton;
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;

/**
 * A Guice module for the transport order type suggestions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderTypeSuggestionsModule
    extends PlantOverviewInjectionModule {

  @Override
  protected void configure() {
    orderTypeSuggestionsBinder().addBinding()
        .to(DefaultOrderTypeSuggestions.class)
        .in(Singleton.class);

    bind(OrderTypeSuggestionsPool.class).in(Singleton.class);
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/test/java/org/opentcs/kernel/extensions/servicewebapi/v1/status/filter/TransportOrderFilterTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.servicewebapi.v1.status.filter;

import java.util.LinkedList;
import org.junit.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderFilterTest {

  private TransportOrder transportOrder1;
  private TransportOrder transportOrder2;
  private TransportOrder transportOrder3;
  private TransportOrder transportOrder4;
  private TransportOrder transportOrder5;
  private TCSObjectReference<Vehicle> vehicle1Reference;

  public TransportOrderFilterTest() {
  }

  @Before
  public void setUp() {
    vehicle1Reference = new Vehicle("Vehicle-001").getReference();
    transportOrder1 = new TransportOrder("TransportOrder-001", new LinkedList<>())
        .withIntendedVehicle(vehicle1Reference);
    transportOrder2 = new TransportOrder("TransportOrder-002", new LinkedList<>())
        .withIntendedVehicle(vehicle1Reference);
    transportOrder3 = new TransportOrder("TransportOrder-003", new LinkedList<>())
        .withIntendedVehicle(new Vehicle("Vehicle-002").getReference());
    transportOrder4 = new TransportOrder("TransportOrder-004", new LinkedList<>())
        .withIntendedVehicle(new Vehicle("Vehicle-003").getReference());
    transportOrder5 = new TransportOrder("TransportOrder-005", new LinkedList<>())
        .withIntendedVehicle(new Vehicle("Vehicle-004").getReference());
  }

  @Test
  public void acceptsAllForNoParams() {
    TransportOrderFilter emptyFilter = new TransportOrderFilter(null);

    assertTrue(emptyFilter.test(transportOrder1));
    assertTrue(emptyFilter.test(transportOrder2));
    assertTrue(emptyFilter.test(transportOrder3));
    assertTrue(emptyFilter.test(transportOrder4));
    assertTrue(emptyFilter.test(transportOrder5));

  }

  @Test
  public void detectsIntendedVehicle1() {
    TransportOrderFilter intendedVehicleFilter
        = new TransportOrderFilter(vehicle1Reference.getName());

    assertTrue(intendedVehicleFilter.test(transportOrder1));
    assertTrue(intendedVehicleFilter.test(transportOrder2));
    assertFalse(intendedVehicleFilter.test(transportOrder3));
    assertFalse(intendedVehicleFilter.test(transportOrder4));
    assertFalse(intendedVehicleFilter.test(transportOrder5));
  }

}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/TripleTextInputPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import javax.swing.text.Document;

/**
 * General input panel with three text fields and optionally:
 * <ul>
 * <li>a message/text</li>
 * <li>labels for the text fields</li>
 * <li>unit labels for the text fields</li>
 * </ul>
 * The input of the text fields can be validated 
 * (see {@link Builder#enableValidation enableValidation}).
 * For instanciation the contained 
 * {@link TripleTextInputPanel.Builder Builder}-class must be used.
 * The <code>Object</code> that is returned by {@link InputPanel#getInput} is
 * an <code>Array</code> of three <code>Strings</code>.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class TripleTextInputPanel
    extends TextInputPanel {

  /**
   * If the panel is resetable this is the value the input is set to when
   * doReset() is called.
   */
  private Object resetValue;
  /**
   * Flag indicating if the content of the first text field is a valid input.
   */
  private boolean inputField1Valid = true;
  /**
   * Flag indicating if the content of the second text field is a valid input.
   */
  private boolean inputField2Valid = true;
  /**
   * Flag indicating if the content of the third text field is a valid input.
   */
  private boolean inputField3Valid = true;

  /** 
   * Create a new <code>TripleTextInputPanel</code>.
   * @param title Title of the panel
   */
  private TripleTextInputPanel(String title) {
    super(title);
    initComponents();
  }

  /**
   * Enable input validation against the given regular expressions. 
   * If a format string is <code>null</code> the related text field is not 
   * validated.
   * @see InputPanel#addValidationListener
   * @param format1 A regular expression for the first text field.
   * @param format2 A regular expression for the second text field.
   * @param format3 A regular expression for the third text field.
   */
  private void enableInputValidation(String format1,
                                     String format2,
                                     String format3) {
    if (format1 != null) {
      inputField1.getDocument().addDocumentListener(new TextInputValidator(format1));
    }
    if (format2 != null) {
      inputField2.getDocument().addDocumentListener(new TextInputValidator(format2));
    }
    if (format3 != null) {
      inputField3.getDocument().addDocumentListener(new TextInputValidator(format3));
    }
  }

  @Override
  protected void captureInput() {
    input = new String[] {inputField1.getText(),
                          inputField2.getText(),
                          inputField3.getText()};
  }

  @Override
  public void doReset() {
    input = resetValue;
  }

  /**
   * Mark the input of the specified <code>Document</code> as valid, if this
   * Document belongs to one of the three text fields in this panel.
   * If <code>valid</code> is <code>true</code> the validity of the other
   * two documents is checked, too. Only if all three text fields contain valid
   * input, the whole input of the panel is marked as valid.
   *
   * @see TextInputPanel#setInputValid(boolean, javax.swing.text.Document)  
   * @param valid true, if the content of the <code>Document</code> is valid
   * @param doc the <code>Document</code>
   */
  @Override
  protected void setInputValid(boolean valid, Document doc) {
    // Find out to which input field the document belongs and check the others
    boolean allValid = valid;
    if (doc == inputField1.getDocument()) {
      inputField1Valid = valid;
      if (!(inputField2Valid && inputField3Valid)) {
        allValid = false;
      }
    }
    else if (doc == inputField2.getDocument()) {
      inputField2Valid = valid;
      if (!(inputField1Valid && inputField3Valid)) {
        allValid = false;
      }
    }
    else if (doc == inputField3.getDocument()) {
      inputField3Valid = valid;
      if (!(inputField1Valid && inputField2Valid)) {
        allValid = false;
      }
    }
    else {
      allValid = false;
    }
    setInputValid(allValid);
  }

  // CHECKSTYLE:OFF
  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    unitLabel3 = new javax.swing.JLabel();
    label3 = new javax.swing.JLabel();
    inputField3 = new javax.swing.JTextField();
    messageLabel = new javax.swing.JLabel();
    label1 = new javax.swing.JLabel();
    inputField1 = new javax.swing.JTextField();
    unitLabel1 = new javax.swing.JLabel();
    label2 = new javax.swing.JLabel();
    inputField2 = new javax.swing.JTextField();
    unitLabel2 = new javax.swing.JLabel();

    setLayout(new java.awt.GridBagLayout());

    unitLabel3.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    unitLabel3.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
    unitLabel3.setText("Unit-Label");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(unitLabel3, gridBagConstraints);

    label3.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    label3.setText("Label");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(label3, gridBagConstraints);

    inputField3.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    inputField3.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
    inputField3.setText("initial Value");
    inputField3.setName("inputField3"); // NOI18N
    inputField3.setPreferredSize(new java.awt.Dimension(70, 20));
    inputField3.addFocusListener(new java.awt.event.FocusAdapter() {
      public void focusGained(java.awt.event.FocusEvent evt) {
        inputField3FocusGained(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(inputField3, gridBagConstraints);
    inputField3.getAccessibleContext().setAccessibleName("");

    messageLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    messageLabel.setText("Message");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.gridwidth = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(messageLabel, gridBagConstraints);

    label1.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    label1.setText("Label");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(label1, gridBagConstraints);

    inputField1.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    inputField1.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
    inputField1.setText("initial Value");
    inputField1.setName("inputField1"); // NOI18N
    inputField1.setPreferredSize(new java.awt.Dimension(70, 20));
    inputField1.addFocusListener(new java.awt.event.FocusAdapter() {
      public void focusGained(java.awt.event.FocusEvent evt) {
        inputField1FocusGained(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(inputField1, gridBagConstraints);
    inputField1.getAccessibleContext().setAccessibleName("");

    unitLabel1.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    unitLabel1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
    unitLabel1.setText("Unit-Label");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(unitLabel1, gridBagConstraints);

    label2.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    label2.setText("Label");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(label2, gridBagConstraints);

    inputField2.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    inputField2.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
    inputField2.setText("initial Value");
    inputField2.setName("inputField2"); // NOI18N
    inputField2.setPreferredSize(new java.awt.Dimension(70, 20));
    inputField2.addFocusListener(new java.awt.event.FocusAdapter() {
      public void focusGained(java.awt.event.FocusEvent evt) {
        inputField2FocusGained(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(inputField2, gridBagConstraints);
    inputField2.getAccessibleContext().setAccessibleName("");

    unitLabel2.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    unitLabel2.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
    unitLabel2.setText("Unit-Label");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(unitLabel2, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents

  private void inputField1FocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inputField1FocusGained
    inputField1.selectAll();
  }//GEN-LAST:event_inputField1FocusGained

  private void inputField2FocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inputField2FocusGained
    inputField2.selectAll();
  }//GEN-LAST:event_inputField2FocusGained

  private void inputField3FocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inputField3FocusGained
    inputField3.selectAll();
  }//GEN-LAST:event_inputField3FocusGained
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JTextField inputField1;
  private javax.swing.JTextField inputField2;
  private javax.swing.JTextField inputField3;
  private javax.swing.JLabel label1;
  private javax.swing.JLabel label2;
  private javax.swing.JLabel label3;
  private javax.swing.JLabel messageLabel;
  private javax.swing.JLabel unitLabel1;
  private javax.swing.JLabel unitLabel2;
  private javax.swing.JLabel unitLabel3;
  // End of variables declaration//GEN-END:variables
  //CHECKSTYLE:ON

  /**
   * See {@link InputPanel.Builder}.
   */
  public static class Builder
      implements InputPanel.Builder {

    /**
     * The panel's title.
     */
    private final String title;
    /**
     * Message to be displayed in the panel.
     */
    private String message;
    /**
     * Labels of for the text fields.
     */
    private final String[] labels = new String[3];
    /**
     * Unit labels of the text fields.
     */
    private final String[] unitLabels = new String[3];
    /**
     * Initial values for the text fields.
     */
    private final String[] initialValues = new String[3];
    /**
     * Regular expressions for validation of the text field contents.
     */
    private final String[] formats = new String[3];
    /**
     * Show a reset button in the panel.
     * Default is <code>false</code>. 
     */
    private boolean resetButton;
    /**
     * Value the input is reset to when the reset button is used.
     */
    private Object resetValue;

    /**
     * Create a new builder.
     * @param title Title of the panel.
     */
    public Builder(String title) {
      this.title = title;
    }

    @Override
    public InputPanel build() {
      TripleTextInputPanel panel = new TripleTextInputPanel(title);
      panel.enableInputValidation(formats[0], formats[1], formats[2]);
      panel.label1.setText(labels[0]);
      panel.label2.setText(labels[1]);
      panel.label3.setText(labels[2]);
      panel.unitLabel1.setText(unitLabels[0]);
      panel.unitLabel2.setText(unitLabels[1]);
      panel.unitLabel3.setText(unitLabels[2]);
      panel.inputField1.setText(initialValues[0]);
      panel.inputField2.setText(initialValues[1]);
      panel.inputField3.setText(initialValues[2]);
      panel.messageLabel.setText(message);
      panel.resetable = resetButton;
      if (panel.resetable) {
        panel.resetValue = resetValue;
      }
      return panel;
    }

    /**
     * Set the labels for the text fields. 
     * Passing <code>null</code> means there should not be such a label.
     * @param label1 The label of the first text field
     * @param label2 The label of the second text field
     * @param label3 The label of the third text field
     * @return the instance of this <code>Builder</code>
     */
    public Builder setLabels(String label1, String label2, String label3) {
      labels[0] = label1;
      labels[1] = label2;
      labels[2] = label3;
      return this;
    }

    /**
     * Set the same initial value for all three text fields.
     * @param value The initial value.
     * @return the isntance of this <code>Builder</code>
     */
    public Builder setInitialValues(String value) {
      return setInitialValues(value, value, value);
    }

    /**
     * Set the initial values for the text fields of the panel
     * Passing <code>null</code> means there should not be an initial value
     * for this text field.
     * @param val1 The initial value of the first text field
     * @param val2 The initial value of the second text field
     * @param val3 The initial value of the third text field
     * @return the instance of this <code>Builder</code>
     */
    public Builder setInitialValues(String val1, String val2, String val3) {
      initialValues[0] = val1;
      initialValues[1] = val2;
      initialValues[2] = val3;
      return this;
    }

    /**
     * Set the same text for the unit label for all three text fields.
     * @param unit The unit 
     * @return the isntance of this <code>Builder</code>
     */
    public Builder setUnitLabels(String unit) {
      return setUnitLabels(unit, unit, unit);
    }

    /**
     * Set the text for the unit labels of the panel.
     * Passing <code>null</code> means there should not be a unit label for
     * the corresponding text field.
     * @param unit1 The unit of the first text field
     * @param unit2 The unit of the second text field
     * @param unit3 The unit of the third text field
     * @return the instance of this <code>Builder</code>
     */
    public Builder setUnitLabels(String unit1, String unit2, String unit3) {
      unitLabels[0] = unit1;
      unitLabels[1] = unit2;
      unitLabels[2] = unit3;
      return this;
    }

    /**
     * Set the message of the panel.
     * The user of this method must take care for the line breaks in the message,
     * as it is not wrapped automatically!
     * @param message the message
     * @return the instance of this <code>Builder</code>
     */
    public Builder setMessage(String message) {
      this.message = message;
      return this;
    }

    public Builder enableValidation(String format) {
      return enableValidation(format, format, format);
    }

    /**
     * Make the panel validate it's input by using the specified regular
     * expressions for the text fields.
     * Passing null as an argument means that the corresponding text field
     * should not be validated.
     * @param format1 The regular expression that will be used for validation in
     *                the first text field.
     * @param format2 The regular expression that will be used for validation in
     *                the second text field.
     * @param format3 The regular expression that will be used for validation in
     *                the third text field.
     * @return the instance of this <code>Builder</code>
     */
    public Builder enableValidation(String format1,
                                    String format2,
                                    String format3) {
      formats[0] = format1;
      formats[1] = format2;
      formats[2] = format3;
      return this;
    }

    /**
     * Set a value the panel's input can be reset to.
     * @param resetValue the reset value
     * @return the instance of this <code>Builder</code>
     */
    public Builder enableResetButton(Object resetValue) {
      this.resetButton = true;
      this.resetValue = resetValue;
      return this;
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/peripherals/jobs/PeripheralJobsContainerListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.peripherals.jobs;

import java.util.Collection;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * Listens for changes to the {@link PeripheralJobsContainer}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralJobsContainerListener {

  /**
   * Notifies the listener that the container has been initialized.
   *
   * @param jobs The jobs the container has been initialized with.
   */
  void containerInitialized(Collection<PeripheralJob> jobs);

  /**
   * Notifies the listener that a job has been added.
   *
   * @param job The job that has been added.
   */
  void peripheralJobAdded(PeripheralJob job);

  /**
   * Notifies the listener that a job has been updated.
   *
   * @param job The job that has been updated.
   */
  void peripheralJobUpdated(PeripheralJob job);

  /**
   * Notifies the listener that a job has been removed.
   *
   * @param job The job that has been removed.
   */
  void peripheralJobRemoved(PeripheralJob job);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/LayoutUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import javax.inject.Inject;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.persistence.ModelManager;

/**
 * Represents a point object in the TreeView.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class LayoutUserObject
    extends FigureUserObject {

  /**
   * Creates a new instance.
   *
   * @param model The corresponding data object
   * @param guiManager The gui manager.
   * @param modelManager The model manager
   */
  @Inject
  public LayoutUserObject(@Assisted LayoutModel model,
                          GuiManager guiManager,
                          ModelManager modelManager) {
    super(model, guiManager, modelManager);
  }

  @Override
  public LayoutModel getModelComponent() {
    return (LayoutModel) super.getModelComponent();
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/BasePlantModelTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;

/**
 * The base class for a plant model transfer object.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlTransient
@XmlAccessorType(XmlAccessType.PROPERTY)
public class BasePlantModelTO {

  private String version = "";

  @XmlAttribute(required = true)
  public String getVersion() {
    return version;
  }

  public BasePlantModelTO setVersion(@Nonnull String version) {
    requireNonNull(version, "version");
    this.version = version;
    return this;
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/menubar/ActionsMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.menus.MenuFactory;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.guing.util.PlantOverviewApplicationConfiguration;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's menu for run-time actions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ActionsMenu
    extends JMenu {

  /**
   * A menu item for assuming the model coordinates from the layout coordinates.
   */
  private final JMenuItem cbiAlignLayoutWithModel;
  /**
   * A menu item for assuming the layout coordinates from the model coordinates.
   */
  private final JMenuItem cbiAlignModelWithLayout;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   * @param drawingEditor The application's drawing editor.
   * @param menuFactory A factory for menu items.
   * @param appConfig The application's configuration.
   */
  @Inject
  public ActionsMenu(ViewActionMap actionMap,
                     OpenTCSDrawingEditor drawingEditor,
                     MenuFactory menuFactory,
                     PlantOverviewApplicationConfiguration appConfig) {
    requireNonNull(actionMap, "actionMap");
    requireNonNull(drawingEditor, "drawingEditor");
    requireNonNull(menuFactory, "menuFactory");
    requireNonNull(appConfig, "appConfig");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);

    this.setText(labels.getString("actionsMenu.text"));
    this.setToolTipText(labels.getString("actionsMenu.tooltipText"));
    this.setMnemonic('A');

    // Menu item Actions -> Copy model to layout
    cbiAlignModelWithLayout = menuFactory.createModelToLayoutMenuItem(true);
    add(cbiAlignModelWithLayout);

    // Menu item Actions -> Copy layout to model
    cbiAlignLayoutWithModel = menuFactory.createLayoutToModelMenuItem(true);
    add(cbiAlignLayoutWithModel);
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/peripherals/jobs/PeripheralJobTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.peripherals.jobs;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import static org.opentcs.util.Assertions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A table model for peripheral jobs.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class PeripheralJobTableModel
    extends AbstractTableModel
    implements PeripheralJobsContainerListener {

  private static final Logger LOG = LoggerFactory.getLogger(PeripheralJobTableModel.class);
  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewOperating.PERIPHERALJOB_PATH);

  public static final int COLUMN_NAME = 0;
  public static final int COLUMN_LOCATION = 1;
  public static final int COLUMN_OPERATION = 2;
  public static final int COLUMN_RELATED_VEHICLE = 3;
  public static final int COLUMN_RELATED_ORDER = 4;
  public static final int COLUMN_STATE = 5;
  public static final int COLUMN_CREATION_TIME = 6;
  /**
   * The column names.
   */
  private static final String[] COLUMN_NAMES = new String[]{
    BUNDLE.getString("peripheralJobTableModel.column_name.headerText"),
    BUNDLE.getString("peripheralJobTableModel.column_location.headerText"),
    BUNDLE.getString("peripheralJobTableModel.column_operation.headerText"),
    BUNDLE.getString("peripheralJobTableModel.column_relatedVehicle.headerText"),
    BUNDLE.getString("peripheralJobTableModel.column_relatedTransportOrder.headerText"),
    BUNDLE.getString("peripheralJobTableModel.column_state.headerText"),
    BUNDLE.getString("peripheralJobTableModel.column_creationTime.headerText")
  };
  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
    String.class,
    String.class,
    String.class,
    TCSObjectReference.class,
    TCSObjectReference.class,
    String.class,
    Instant.class
  };
  /**
   * The entries in the table.
   */
  private final List<PeripheralJob> entries = new ArrayList<>();

  /**
   * Creates a new instance.
   */
  public PeripheralJobTableModel() {
  }

  @Override
  public int getRowCount() {
    return entries.size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return null;
    }

    PeripheralJob entry = entries.get(rowIndex);
    switch (columnIndex) {
      case COLUMN_NAME:
        return entry.getName();
      case COLUMN_LOCATION:
        return entry.getPeripheralOperation().getLocation().getName();
      case COLUMN_OPERATION:
        return entry.getPeripheralOperation().getOperation();
      case COLUMN_RELATED_VEHICLE:
        return entry.getRelatedVehicle();
      case COLUMN_RELATED_ORDER:
        return entry.getRelatedTransportOrder();
      case COLUMN_STATE:
        return entry.getState().name();
      case COLUMN_CREATION_TIME:
        return entry.getCreationTime();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public void containerInitialized(Collection<PeripheralJob> jobs) {
    requireNonNull(jobs, "jobs");

    SwingUtilities.invokeLater(() -> {
      // Notifiations of any change listeners must happen at the same time/in the same thread the 
      // data behind the model is updated. Otherwise, there is a risk that listeners work with/
      // refer to outdated data, which can lead to runtime exceptions.
      entries.clear();
      entries.addAll(jobs);
      fireTableDataChanged();
    });
  }

  @Override
  public void peripheralJobAdded(PeripheralJob job) {
    requireNonNull(job, "job");

    SwingUtilities.invokeLater(() -> {
      entries.add(job);
      fireTableRowsInserted(entries.size() - 1, entries.size() - 1);
    });
  }

  @Override
  public void peripheralJobUpdated(PeripheralJob job) {
    requireNonNull(job, "job");

    SwingUtilities.invokeLater(() -> {
      int jobIndex = entries.indexOf(job);
      if (jobIndex == -1) {
        LOG.warn("Unknown job: {}. Ignoring job update.", job.getName());
        return;
      }

      entries.set(jobIndex, job);
      fireTableRowsUpdated(jobIndex, jobIndex);
    });
  }

  @Override
  public void peripheralJobRemoved(PeripheralJob job) {
    requireNonNull(job, "job");

    SwingUtilities.invokeLater(() -> {
      int jobIndex = entries.indexOf(job);
      if (jobIndex == -1) {
        LOG.warn("Unknown job: {}. Ignoring job removal.", job.getName());
        return;
      }

      entries.remove(jobIndex);
      fireTableRowsDeleted(jobIndex, jobIndex);
    });
  }

  public PeripheralJob getEntryAt(int index) {
    checkArgument(index >= 0 && index < entries.size(),
                  "index must be in 0..%d: %d",
                  entries.size(),
                  index);
    return entries.get(index);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/package-info.java<|end_filename|>
/**
 * Interfaces and classes defining internal and external interfaces for the openTCS kernel.
 */
package org.opentcs.components.kernel.services;


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/PeripheralInteraction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.drivers.vehicle.MovementCommand;
import static org.opentcs.util.Assertions.checkState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Describes an interaction with any number of peripheral devices.
 * <p>
 * An interaction is always associated with a {@link MovementCommand} and contains
 * {@link PeripheralOperation}s for which {@link PeripheralJob}s are created once the interaction
 * is started.
 * </p>
 * <p>
 * In case there are no operations with the completion required flag set, the interaction is marked
 * as finished immediately after it was started.
 * In case there are operations with the completion required flag set, the interaction is only
 * marked as finished after all corresponding jobs have been processed by the respective peripheral
 * device.
 * </p>
 * <p>
 * Once the interaction is finished, an interaction-specific callback is executed.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralInteraction {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralInteraction.class);
  /**
   * The reference to the vehicle that's interacting with peripheral devices.
   */
  private final TCSObjectReference<Vehicle> vehicleRef;
  /**
   * The movement command this interaction is associated with.
   */
  private final MovementCommand movementCommand;
  /**
   * The operations that jobs have to be created for.
   */
  private final List<PeripheralOperation> operations;
  /**
   * The jobs that are required to be finished in order for this interaction itself to be marked as
   * finished.
   */
  private final List<PeripheralJob> requiredJobs = new ArrayList<>();
  /**
   * The peripheral job service to use for creating jobs.
   */
  private final PeripheralJobService peripheralJobService;
  /**
   * The reservation token to use for creating jobs.
   */
  private final String reservationToken;
  /**
   * The callback that is to be executed if the interaction succeeds.
   */
  private Runnable interactionSucceededCallback;
  /**
   * The callback that is executed if the interaction fails.
   */
  private Runnable interactionFailedCallback;
  /**
   * The state of the interaction.
   */
  private State state = State.PRISTINE;

  /**
   * Creates a new instance.
   *
   * @param vehicleRef The reference to the vehicle that's interacting with peripheral devices.
   * @param movementCommand The movement command this interaction is associated with.
   * @param operations The operations that jobs have to be created for.
   * @param peripheralJobService The peripheral job service to use for creating jobs.
   * @param reservationToken The reservation token to use for creating jobs.
   */
  public PeripheralInteraction(@Nonnull TCSObjectReference<Vehicle> vehicleRef,
                               @Nonnull MovementCommand movementCommand,
                               @Nonnull List<PeripheralOperation> operations,
                               @Nonnull PeripheralJobService peripheralJobService,
                               @Nonnull String reservationToken) {
    this.vehicleRef = requireNonNull(vehicleRef, "vehicleRef");
    this.movementCommand = requireNonNull(movementCommand, "movementCommand");
    this.operations = requireNonNull(operations, "operations");
    this.peripheralJobService = requireNonNull(peripheralJobService, "peripheralJobService");
    this.reservationToken = requireNonNull(reservationToken, "reservationToken");
  }

  /**
   * Starts this peripheral interaction.
   *
   * @param interactionSucceededCallback The callback that is to be executed if the interaction
   * succeeds.
   * @param interactionFailedCallback The callback that is to be executed if the interaction fails.
   */
  public void start(@Nonnull Runnable interactionSucceededCallback,
                    @Nonnull Runnable interactionFailedCallback) {
    this.interactionSucceededCallback = requireNonNull(interactionSucceededCallback,
                                                       "interactionSucceededCallback");
    this.interactionFailedCallback = requireNonNull(interactionFailedCallback,
                                                    "interactionFailedCallback");

    LOG.debug("{}: Starting peripheral interaction for movement to {}",
              vehicleRef.getName(),
              movementCommand.getStep().getDestinationPoint().getName());
    for (PeripheralOperation operation : operations) {
      PeripheralJob job = createPeripheralJob(operation);
      if (operation.isCompletionRequired()) {
        requiredJobs.add(job);
      }
    }

    state = State.STARTED;

    if (requiredJobs.isEmpty()) {
      onInteractionFinished();
    }
  }

  /**
   * Informs this interaction that a peripheral job (that might be of interest for this interaction)
   * has been finished.
   *
   * @param job The peripheral job that has been finished.
   */
  public void onPeripheralJobFinished(@Nonnull PeripheralJob job) {
    requireNonNull(job, "job");
    if (requiredJobs.remove(job) && requiredJobs.isEmpty()) {
      // The last required job has been finished.
      onInteractionFinished();
    }
  }

  /**
   * Informs this interaction that a peripheral job (that might be of interest for this interaction)
   * has failed.
   *
   * @param job The peripheral job that has failed.
   */
  public void onPeripheralJobFailed(@Nonnull PeripheralJob job) {
    requireNonNull(job, "job");
    if (requiredJobs.contains(job)) {
      onInteractionFailed();
    }
  }

  /**
   * Returns the movement command this interaction is associated with.
   *
   * @return The movement command this interaction is associated with.
   */
  public MovementCommand getMovementCommand() {
    return movementCommand;
  }

  /**
   * Returns whether the interaction is finished.
   *
   * @return Whether the interaction is finished.
   */
  public boolean isFinished() {
    return hasState(State.FINSHED);
  }

  /**
   * Returns whether the interaction has failed.
   *
   * @return Whether the interaction has failed.
   */
  public boolean isFailed() {
    return hasState(State.FAILED);
  }

  /**
   * Returns whether the interaction is in the given state.
   *
   * @param state The state.
   * @return Whether the interaction is in the given state.
   */
  public boolean hasState(State state) {
    return this.state == state;
  }

  /**
   * Returns whether this interaction has some operations that are required to be completed.
   *
   * @return Whether this interaction has some operations that are required to be completed.
   */
  public boolean hasRequiredOperations() {
    return operations.stream()
        .anyMatch(PeripheralOperation::isCompletionRequired);
  }

  /**
   * Returns the list of operations that are required to be completed and that haven't been
   * completed yet.
   *
   * @return A list of operations.
   */
  public List<PeripheralOperation> getPendingRequiredOperations() {
    // If we're already done interacting with the peripheral device, there cannot be any pending
    // operations.
    if (hasState(State.FINSHED)) {
      return new ArrayList<>();
    }

    if (!hasRequiredOperations()) {
      return new ArrayList<>();
    }

    if (!requiredJobs.isEmpty()) {
      // The interaction is still ongoing. Jobs are not yet finished or have even failed.
      return requiredJobs.stream()
          .map(job -> job.getPeripheralOperation())
          .collect(Collectors.toList());
    }

    // The interaction is still ongoing but no jobs have been created (yet) for the required
    // operations.
    return operations.stream()
        .filter(PeripheralOperation::isCompletionRequired)
        .collect(Collectors.toList());
  }

  private void onInteractionFinished() {
    checkState(interactionSucceededCallback != null, "The interaction hasn't been started yet.");
    checkState(!hasState(State.FAILED), "The interaction has already been marked as failed.");
    checkState(!hasState(State.FINSHED), "The interaction has already been marked as finished.");
    state = State.FINSHED;

    LOG.debug("{}: Peripheral interaction finished for movement to {}",
              vehicleRef.getName(),
              movementCommand.getStep().getDestinationPoint().getName());
    interactionSucceededCallback.run();
  }

  private PeripheralJob createPeripheralJob(PeripheralOperation operation) {
    return peripheralJobService.createPeripheralJob(
        new PeripheralJobCreationTO("Job-",
                                    reservationToken,
                                    new PeripheralOperationCreationTO(
                                        operation.getOperation(),
                                        operation.getLocation().getName()
                                    ))
            .withIncompleteName(true)
    );
  }

  private void onInteractionFailed() {
    checkState(interactionFailedCallback != null, "The interaction hasn't been started yet.");
    checkState(!hasState(State.FINSHED), "The interaction has already been marked as finished.");
    checkState(!hasState(State.FAILED), "The interaction has already been marked as failed.");
    state = State.FAILED;

    LOG.debug("{}: Peripheral interaction failed for movement to {}",
              vehicleRef.getName(),
              movementCommand.getStep().getDestinationPoint().getName());
    interactionFailedCallback.run();
  }

  public enum State {
    /**
     * The interaction is initialized and yet to be started.
     */
    PRISTINE,
    /**
     * The interaction was started.
     */
    STARTED,
    /**
     * The interaction was finished.
     * All of the required operations (if any) have been finished successfully.
     */
    FINSHED,
    /**
     * The interaction has failed.
     * At least one of the required operations failed.
     */
    FAILED;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/extensions/controlcenter/vehicles/VehicleEntryPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.controlcenter.vehicles;

import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.TreeMap;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides a pool of {@link VehicleEntry}s with an entry for every {@link Vehicle} object in the
 * kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleEntryPool
    implements Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(VehicleEntryPool.class);
  /**
   * The object service.
   */
  private final TCSObjectService objectService;
  /**
   * The entries of this pool.
   */
  private final Map<String, VehicleEntry> entries = new TreeMap<>();
  /**
   * Whether the pool is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param objectService The object service.
   */
  @Inject
  public VehicleEntryPool(@Nonnull TCSObjectService objectService) {
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      LOG.debug("Already initialized.");
      return;
    }

    objectService.fetchObjects(Vehicle.class).stream()
        .forEach(vehicle -> entries.put(vehicle.getName(), new VehicleEntry(vehicle)));
    LOG.debug("Initialized vehicle entry pool: {}", entries);
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      LOG.debug("Not initialized.");
      return;
    }

    entries.clear();
    initialized = false;
  }

  /**
   * Returns all entries in the pool.
   *
   * @return Map of vehicle names to their vehicle entries.
   */
  @Nonnull
  public Map<String, VehicleEntry> getEntries() {
    return entries;
  }

  /**
   * Returns the {@link VehicleEntry} for the given vehicle name.
   *
   * @param vehicleName The vehicle name to get the entry for.
   * @return the vehicle entry for the given vehicle name.
   */
  @Nullable
  public VehicleEntry getEntryFor(@Nonnull String vehicleName) {
    requireNonNull(vehicleName, "vehicleName");
    return entries.get(vehicleName);
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/guiceConfig/java/org/opentcs/guing/plugins/panels/statistics/StatisticsPanelModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.statistics;

import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Configures the statistics panel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatisticsPanelModule
    extends PlantOverviewInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StatisticsPanelModule.class);

  @Override
  protected void configure() {
    StatisticsPanelConfiguration configuration
        = getConfigBindingProvider().get(StatisticsPanelConfiguration.PREFIX,
                                         StatisticsPanelConfiguration.class);

    if (!configuration.enable()) {
      LOG.info("Statistics panel disabled by configuration.");
      return;
    }

    pluggablePanelFactoryBinder().addBinding().to(StatisticsPanelFactory.class);
  }
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/RegistryProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.components.Lifecycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides the one {@link Registry} instance used for RMI communication.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RegistryProvider
    implements Lifecycle {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(RegistryProvider.class);
  /**
   * Provides socket factories used to create RMI registries.
   */
  private final SocketFactoryProvider socketFactoryProvider;
  /**
   * This class' configuration.
   */
  private final RmiKernelInterfaceConfiguration configuration;
  /**
   * The actual registry instance.
   */
  private Registry registry;
  /**
   * Whether this provider is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param socketFactoryProvider The socket factory provider used for RMI.
   * @param configuration This class' configuration.
   */
  @Inject
  public RegistryProvider(@Nonnull SocketFactoryProvider socketFactoryProvider,
                          @Nonnull RmiKernelInterfaceConfiguration configuration) {
    this.socketFactoryProvider = requireNonNull(socketFactoryProvider, "socketFactoryProvider");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      LOG.debug("Already initialized.");
      return;
    }

    installRegistry();

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      LOG.debug("Not initialized.");
      return;
    }

    registry = null;

    initialized = false;
  }

  @Nonnull
  public Registry get() {
    return registry;
  }

  private void installRegistry() {
    try {
      LOG.debug("Trying to create a local registry...");
      registry = LocateRegistry.createRegistry(configuration.registryPort(),
                                               socketFactoryProvider.getClientSocketFactory(),
                                               socketFactoryProvider.getServerSocketFactory());
      // Make sure the registry is running
      registry.list();
    }
    catch (RemoteException ex) {
      LOG.error("Couldn't create a working local registry.");
      registry = null;
      throw new RuntimeException(ex);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/adapter/LocationAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import java.util.Map;
import static java.util.Objects.requireNonNull;
import org.opentcs.access.to.model.LocationCreationTO;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectPropConstants;
import static org.opentcs.data.ObjectPropConstants.LOC_DEFAULT_REPRESENTATION;
import org.opentcs.data.TCSObject;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An adapter for locations.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class LocationAdapter
    extends AbstractProcessAdapter {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LocationAdapter.class);

  @Override  // OpenTCSProcessAdapter
  public void updateModelProperties(TCSObject<?> tcsObject,
                                    ModelComponent modelComponent,
                                    SystemModel systemModel,
                                    TCSObjectService objectService) {
    Location location = requireNonNull((Location) tcsObject, "tcsObject");
    LocationModel model = (LocationModel) modelComponent;

    try {
      // Name 
      model.getPropertyName().setText(location.getName());

      // Position in model
      model.getPropertyModelPositionX().setValueAndUnit(location.getPosition().getX(),
                                                        LengthProperty.Unit.MM);
      model.getPropertyModelPositionY().setValueAndUnit(location.getPosition().getY(),
                                                        LengthProperty.Unit.MM);

      // Type
      model.getPropertyType().setValue(location.getType().getName());
      model.getPropertyLocked().setValue(location.isLocked());

      // Peripheral information
      model.getPropertyPeripheralReservationToken().setText(location.getPeripheralInformation().getReservationToken());
      model.getPropertyPeripheralState().setText(location.getPeripheralInformation().getState().name());
      model.getPropertyPeripheralProcState().setText(location.getPeripheralInformation().getProcState().name());
      model.getPropertyPeripheralJob().setText(extractPeripheralJobName(location));

      // Misc properties
      updateMiscModelProperties(model, location);
      updateModelLayoutProperties(model, location, systemModel.getLayoutModel());
      // look for label and symbol
      updateRepresentation(model, model.getPropertyMiscellaneous());

      model.setLocation(location);
      model.propertiesChanged(model);
    }
    catch (IllegalArgumentException e) {
      LOG.warn("", e);
    }
  }

  @Override
  public PlantModelCreationTO storeToPlantModel(ModelComponent modelComponent,
                                                SystemModel systemModel,
                                                PlantModelCreationTO plantModel) {
    LocationModel locationModel = (LocationModel) modelComponent;

    PlantModelCreationTO result = plantModel
        .withLocation(
            new LocationCreationTO(modelComponent.getName(),
                                   locationModel.getLocationType().getName(),
                                   getPosition(locationModel))
                .withLocked(getLocked(locationModel))
                .withProperties(getKernelProperties(modelComponent))
                .withLayout(getLayout(locationModel))
        );

    unmarkAllPropertiesChanged(modelComponent);

    return result;
  }

  @Override
  protected Map<String, String> getKernelProperties(ModelComponent model) {
    Map<String, String> result = super.getKernelProperties(model);

    LocationRepresentation locationRepresentation
        = ((LocationModel) model).getPropertyDefaultRepresentation().getLocationRepresentation();

    if (locationRepresentation != null) {
      result.put(LOC_DEFAULT_REPRESENTATION, locationRepresentation.name());
    }

    return result;
  }

  private void updateRepresentation(LocationModel model, KeyValueSetProperty miscellaneous) {
    for (KeyValueProperty kvp : miscellaneous.getItems()) {
      switch (kvp.getKey()) {
        case ObjectPropConstants.LOC_DEFAULT_REPRESENTATION:
          model.getPropertyDefaultRepresentation().setLocationRepresentation(
              LocationRepresentation.valueOf(kvp.getValue()));
          break;
        default:
      }
    }
  }

  private void updateModelLayoutProperties(LocationModel model,
                                           Location location,
                                           LayoutModel layoutModel) {
    model.getPropertyLayoutPositionX()
        .setText(String.valueOf(location.getLayout().getPosition().getX()));
    model.getPropertyLayoutPositionY()
        .setText(String.valueOf(location.getLayout().getPosition().getY()));
    model.getPropertyLabelOffsetX()
        .setText(String.valueOf(location.getLayout().getLabelOffset().getX()));
    model.getPropertyLabelOffsetY()
        .setText(String.valueOf(location.getLayout().getLabelOffset().getY()));
    model.getPropertyDefaultRepresentation()
        .setLocationRepresentation(location.getLayout().getLocationRepresentation());
    LayerWrapper layerWrapper = layoutModel.getPropertyLayerWrappers()
        .getValue().get(location.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);
  }

  private String extractPeripheralJobName(Location location) {
    return location.getPeripheralInformation().getPeripheralJob() == null
        ? null
        : location.getPeripheralInformation().getPeripheralJob().getName();
  }

  private Triple getPosition(LocationModel model) {
    return convertToTriple(model.getPropertyModelPositionX(),
                           model.getPropertyModelPositionY());
  }

  private boolean getLocked(LocationModel model) {
    if (model.getPropertyLocked().getValue() instanceof Boolean) {
      return (boolean) model.getPropertyLocked().getValue();
    }
    return false;
  }

  private LocationCreationTO.Layout getLayout(LocationModel model) {
    return new LocationCreationTO.Layout(
        new Couple(Long.parseLong(model.getPropertyLayoutPositionX().getText()),
                   Long.parseLong(model.getPropertyLayoutPositionY().getText())),
        new Couple(Long.parseLong(model.getPropertyLabelOffsetX().getText()),
                   Long.parseLong(model.getPropertyLabelOffsetY().getText())),
        model.getPropertyDefaultRepresentation().getLocationRepresentation(),
        model.getPropertyLayerWrapper().getValue().getLayer().getId()
    );
  }

  private Triple convertToTriple(CoordinateProperty cpx, CoordinateProperty cpy) {
    Triple result = new Triple((int) cpx.getValueByUnit(LengthProperty.Unit.MM),
                               (int) cpy.getValueByUnit(LengthProperty.Unit.MM),
                               0);

    return result;
  }
}


<|start_filename|>openTCS-Common/src/test/java/org/opentcs/util/persistence/V004DrivingCoursePersistenceTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.junit.*;
import static org.junit.Assert.assertTrue;
import org.opentcs.util.persistence.v004.AllowedOperationTO;
import org.opentcs.util.persistence.v004.BlockTO;
import org.opentcs.util.persistence.v004.LocationTO;
import org.opentcs.util.persistence.v004.LocationTO.Link;
import org.opentcs.util.persistence.v004.LocationTypeTO;
import org.opentcs.util.persistence.v004.MemberTO;
import org.opentcs.util.persistence.v004.PathTO;
import org.opentcs.util.persistence.v004.PointTO;
import org.opentcs.util.persistence.v004.PointTO.OutgoingPath;
import org.opentcs.util.persistence.v004.PropertyTO;
import org.opentcs.util.persistence.v004.V004PlantModelTO;
import org.opentcs.util.persistence.v004.VehicleTO;
import org.opentcs.util.persistence.v004.VisualLayoutTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V004DrivingCoursePersistenceTest {

  private static final Logger LOG = LoggerFactory.getLogger(V004DrivingCoursePersistenceTest.class);

  public V004DrivingCoursePersistenceTest() {
  }

  @Test
  public void testToXml()
      throws IOException {
    V004PlantModelTO model = new V004PlantModelTO();
    model.setVersion("0.0.4");
    model.setName("Demo");

    PointTO point1 = createPoint("Point1", 1, 2, 3, Float.NaN, "HALT_POSITION",
                                 Arrays.asList(createOutgoingPath("Path1")),
                                 new ArrayList<>());
    PointTO point2 = createPoint("Point2", 4, 5, 6, Float.NaN, "PARK_POSITION",
                                 Arrays.asList(createOutgoingPath("Path2"),
                                               createOutgoingPath("Path3")),
                                 new ArrayList<>());
    model.setPoints(Arrays.asList(point1, point2));

    PathTO path1 = createPath();
    model.setPaths(Arrays.asList(path1));

    VehicleTO vehicle = createVehicle();
    model.setVehicles(Arrays.asList(vehicle));

    LocationTypeTO locType = createLocationType();

    model.setLocationTypes(Arrays.asList(locType));

    LocationTO loc = createLocation();
    model.setLocations(Arrays.asList(loc));

    BlockTO block = createBlock();
    model.setBlocks(Arrays.asList(block));

    model.setVisualLayout(createVisualLayout());

    StringWriter writer = new StringWriter();
    model.toXml(writer);

    String xmlOutput = writer.toString();
    LOG.info(xmlOutput);

    try {
      assertTrue(validateXml(new StringReader(xmlOutput)));
    }
    catch (SAXException | IOException ex) {
      LOG.error("", ex);
    }
  }

  private boolean validateXml(Reader reader)
      throws SAXException, IOException {
    Source schemaFile = new StreamSource(getClass().getResourceAsStream(
        "/org/opentcs/util/persistence/model-0.0.4.xsd"));
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = schemaFactory.newSchema(schemaFile);
    try {
      schema.newValidator().validate(new StreamSource(reader));
      LOG.info("XML is valid.");
      return true;
    }
    catch (SAXException e) {
      LOG.info("XML is NOT valid.", e);
      return false;
    }
  }

  private PointTO createPoint(String name, long xPosition, long yPosition, long zPosition,
                              Float vehicleOrientationAngle, String type,
                              List<OutgoingPath> outgoingPaths,
                              List<PropertyTO> properties) {
    PointTO p = new PointTO();
    p.setName(name);
    p.setProperties(properties);
    p.setxPosition(xPosition);
    p.setyPosition(yPosition);
    p.setzPosition(zPosition);
    p.setVehicleOrientationAngle(vehicleOrientationAngle);
    p.setType(type);
    p.setOutgoingPaths(outgoingPaths);
    p.setPointLayout(new PointTO.PointLayout()
        .setxPosition(xPosition)
        .setyPosition(yPosition)
        .setxLabelOffset(20L)
        .setyLabelOffset(20L)
        .setLayerId(0));
    return p;
  }

  private OutgoingPath createOutgoingPath(String name) {
    OutgoingPath op = new OutgoingPath();
    op.setName(name);
    return op;
  }

  private PathTO createPath() {
    PathTO p = new PathTO();
    p.setName("Point1 --- Point2");
    p.setSourcePoint("Point1");
    p.setDestinationPoint("Point2");
    p.setLength(100L);
    p.setMaxVelocity(1000L);
    p.setMaxReverseVelocity(200L);
    p.setLocked(false);
    p.setPathLayout(new PathTO.PathLayout()
        .setConnectionType("DIRECT")
        .setControlPoints(new ArrayList<>())
        .setLayerId(0));

    PropertyTO property = new PropertyTO();
    property.setName("Property1");
    property.setValue("Value1");
    p.setProperties(Arrays.asList(property));
    return p;
  }

  private LocationTypeTO createLocationType() {
    LocationTypeTO locType = new LocationTypeTO();

    locType.setName("Transfer station");

    AllowedOperationTO ao1 = new AllowedOperationTO();
    ao1.setName("NOP");
    AllowedOperationTO ao2 = new AllowedOperationTO();
    ao2.setName("Load cargo");
    locType.setAllowedOperations(Arrays.asList(ao1, ao2));

    locType.setLocationTypeLayout(new LocationTypeTO.LocationTypeLayout()
        .setLocationRepresentation("LOAD_TRANSFER_GENERIC"));

    return locType;
  }

  private LocationTO createLocation() {
    LocationTO loc = new LocationTO();

    loc.setName("Storage 02");
    loc.setxPosition(100L);
    loc.setyPosition(200L);
    loc.setzPosition(300L);
    loc.setType("Transfer station");
    loc.setLocationLayout(new LocationTO.LocationLayout()
        .setxPosition(100L)
        .setyPosition(200L)
        .setxLabelOffset(20L)
        .setyLabelOffset(20L)
        .setLocationRepresentation("LOAD_TRANSFER_GENERIC")
        .setLayerId(0));

    Link link = new Link();
    link.setPoint("Point1");
    loc.setLinks(Arrays.asList(link));

    return loc;
  }

  private BlockTO createBlock() {
    BlockTO block = new BlockTO();
    block.setName("Block-001");

    MemberTO member = new MemberTO();
    member.setName("Point1 --- Point2");
    block.setMembers(Arrays.asList(member));

    block.setBlockLayout(new BlockTO.BlockLayout()
        .setColor("#FF0000"));

    return block;
  }

  private VisualLayoutTO createVisualLayout() {
    VisualLayoutTO vl = new VisualLayoutTO();
    vl.setName("VLayout-01");
    vl.setScaleX(50.0f);
    vl.setScaleY(50.0f);
    vl.setLayers(Arrays.asList(new VisualLayoutTO.Layer()
        .setId(0)
        .setOrdinal(0)
        .setVisible(Boolean.TRUE)
        .setName("Layer 0")
        .setGroupId(0)));
    vl.setLayerGroups(Arrays.asList(new VisualLayoutTO.LayerGroup()
        .setId(0)
        .setName("Layer group 0")
        .setVisible(Boolean.TRUE)));

    PropertyTO property = new PropertyTO();
    property.setName("tcs:vehicleThemeClass");
    property.setValue("...");
    vl.setProperties(Arrays.asList(property));

    return vl;
  }

  private VehicleTO createVehicle() {
    VehicleTO vehicle = new VehicleTO();
    vehicle.setName("Vehicle-01");
    vehicle.setLength(1000L);
    vehicle.setEnergyLevelCritical(30L);
    vehicle.setEnergyLevelGood(90L);
    vehicle.setVehicleLayout(new VehicleTO.VehicleLayout()
        .setColor("#FF0000"));
    return vehicle;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/liner/BezierLinerEdit.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures.liner;

import javax.swing.SwingUtilities;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import org.jhotdraw.draw.BezierFigure;
import org.jhotdraw.draw.event.BezierNodeEdit;
import org.jhotdraw.geom.BezierPath;
import org.opentcs.guing.components.drawing.figures.PathConnection;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 *
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class BezierLinerEdit
    extends javax.swing.undo.AbstractUndoableEdit {

  private final BezierFigure fOwner;
  private final BezierNodeEdit fNodeEdit;

  /**
   * @param owner A path
   */
  public BezierLinerEdit(BezierFigure owner) {
    fOwner = owner;
    BezierPath.Node node = owner.getNode(0);
    fNodeEdit = new BezierNodeEdit(owner, 0, node, node);
  }

  /**
   *
   * @return The associated PathConnection
   */
  public BezierFigure getOwner() {
    return fOwner;
  }

  @Override // AbstractUndoableEdit
  public boolean isSignificant() {
    return false;
  }

  @Override // AbstractUndoableEdit
  public String getPresentationName() {
    return ResourceBundleUtil.getBundle(I18nPlantOverview.MISC_PATH)
        .getString("bezierLinerEdit.presentationName");
  }

  @Override // AbstractUndoableEdit
  public void redo() throws CannotRedoException {
    fNodeEdit.redo();
    updateProperties();
  }

  @Override // AbstractUndoableEdit
  public void undo() throws CannotUndoException {
    fNodeEdit.undo();
    updateProperties();
  }

  private void updateProperties() {
    SwingUtilities.invokeLater(() -> {
      PathConnection path = (PathConnection) fOwner;
      path.updateControlPoints();
      path.getModel().getPropertyPathControlPoints().markChanged();
      path.getModel().propertiesChanged(path);
    });
  }
}


<|start_filename|>openTCS-API-Injection/src/main/java/overview.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
  <body>
    This is the description of the openTCS injection API.

    <p>
      Tutorials/code examples can be found in the developer's guide that is also part of the
      openTCS distribution.
    </p>
  </body>
</html>


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/menus/menubar/HelpMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.action.app.AboutAction;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's "Help" menu.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class HelpMenu
    extends JMenu {

  /**
   * A menu item for showing the application's "about" panel.
   */
  private final JMenuItem menuItemAbout;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   */
  @Inject
  public HelpMenu(ViewActionMap actionMap) {
    requireNonNull(actionMap, "actionMap");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.MENU_PATH);

    this.setText(labels.getString("helpMenu.text"));
    this.setToolTipText(labels.getString("helpMenu.tooltipText"));
    this.setMnemonic('?');

    menuItemAbout = add(actionMap.get(AboutAction.ID));
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/GuiManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import org.opentcs.components.plantoverview.PlantModelExporter;
import org.opentcs.components.plantoverview.PlantModelImporter;
import org.opentcs.guing.model.ModelComponent;

/**
 * Provides some central services for various parts of the plant overview application.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface GuiManager {

  /**
   * Called when an object was selected in the tree view.
   *
   * @param modelComponent The selected object.
   */
  void selectModelComponent(ModelComponent modelComponent);

  /**
   * Called when an additional object was selected in the tree view.
   *
   * @param modelComponent The selected object.
   */
  void addSelectedModelComponent(ModelComponent modelComponent);

  /**
   * Called when an object was removed from the tree view (by user interaction).
   *
   * @param fDataObject The object to be removed.
   * @return Indicates whether the object was really removed from the model.
   */
  boolean treeComponentRemoved(ModelComponent fDataObject);

  /**
   * Notifies about a figure object being selected.
   *
   * @param modelComponent The selected object.
   */
  void figureSelected(ModelComponent modelComponent);

  /**
   * Creates a new, empty model and initializes it.
   */
  void createEmptyModel();

  /**
   * Loads a plant model.
   */
  void loadModel();
  
  /**
   * Imports a plant model using the given importer.
   *
   * @param importer The importer.
   */
  void importModel(PlantModelImporter importer);

  /**
   * @return
   */
  boolean saveModel();

  /**
   *
   * @return
   */
  boolean saveModelAs();
  
  /**
   * Exports a plant model using the given exporter.
   *
   * @param exporter The exporter.
   */
  void exportModel(PlantModelExporter exporter);

  /**
   * Creates a new model component instance that does not have a corresponding figure.
   * (Like a block or a location type.)
   *
   * @param clazz The type of object to be created.
   * @return The created object.
   */
  ModelComponent createModelComponent(Class<? extends ModelComponent> clazz);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralCommAdapterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Location;

/**
 * Provides communication adapter instances for peripheral devices to be controlled.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralCommAdapterFactory
    extends Lifecycle {

  /**
   * Returns a {@link PeripheralCommAdapterDescription} for the factory/the adapters provided.
   *
   * @return A {@link PeripheralCommAdapterDescription} for the factory/the adapters provided.
   */
  @Nonnull
  PeripheralCommAdapterDescription getDescription();

  /**
   * Checks whether this factory can provide a communication adapter for the given
   * location/peripheral device.
   *
   * @param location The location to check for.
   * @return {@code true} if, and only if, this factory can provide a communication adapter to
   * control the given location/peripheral device.
   */
  boolean providesAdapterFor(@Nonnull Location location);

  /**
   * Returns a communication adapter for controlling the given location/peripheral device.
   *
   * @param location The location/peripheral device to be controlled.
   * @return A communication adapter for controlling the given location/peripheral device, or
   * {@code null}, if this factory cannot provide an adapter for it.
   */
  @Nullable
  PeripheralCommAdapter getAdapterFor(@Nonnull Location location);
}


<|start_filename|>openTCS-PlantOverview-Base/src/test/java/org/opentcs/guing/components/properties/type/AnglePropertyTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;
import org.opentcs.guing.components.properties.type.AngleProperty.Unit;
import org.opentcs.guing.model.AbstractModelComponent;

/**
 * A test for an angle property.
 * For Degrees, min value is 0 and max value is 360.
 * For Radians, min value is 0 and max value is 2*PI ~ 6.283185
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class AnglePropertyTest {

  private AngleProperty property;

  @ParameterizedTest
  @ValueSource(strings = {"deg", "rad"})
  public void testValidUnits(String unit) {
    property = new AngleProperty(new DummyComponent());
    assertTrue(property.isPossibleUnit(unit));
  }

  @Test
  public void testPropertyConversionDegToRad() {
    // 180 deg = PI rad
    property = new AngleProperty(new DummyComponent(), 180, Unit.DEG);
    property.convertTo(Unit.RAD);
    assertEquals(Math.PI, (double) property.getValue(), 0);
    assertEquals(Unit.RAD, property.getUnit());
  }

  @Test
  public void testPropertyConversionRadToDeg() {
    // 3.7168 rad ~ 212.96 deg
    property = new AngleProperty(new DummyComponent(), 3.7168, Unit.RAD);
    property.convertTo(Unit.DEG);
    assertEquals(212.96, (double) property.getValue(), 0.01);
    assertEquals(Unit.DEG, property.getUnit());
  }

  @Test
  public void testPropertyRange() {
    property = new AngleProperty(new DummyComponent());
    assertEquals(0, property.getValidRange().getMin(), 0);
    assertEquals(Double.MAX_VALUE, property.getValidRange().getMax(), 0);
  }

  @Test
  public void shouldStayInRangeDeg() {
    property = new AngleProperty(new DummyComponent(), 540, Unit.DEG);
    assertEquals(180.0, property.getValue());
    assertEquals(Unit.DEG, property.getUnit());
  }

  @Test
  public void shouldStayInRangeRad() {
    property = new AngleProperty(new DummyComponent(), 10, Unit.RAD);
    assertEquals(3.716, (double) property.getValue(), 0.001);
    assertEquals(AngleProperty.Unit.RAD, property.getUnit());
  }

  private class DummyComponent
      extends AbstractModelComponent {
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/PointFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import com.google.inject.assistedinject.Assisted;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.geom.Geom;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.components.drawing.DrawingOptions;
import org.opentcs.guing.components.drawing.Strokes;
import org.opentcs.guing.components.drawing.ZoomPoint;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * A figure that represents a decision point.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PointFigure
    extends TCSFigure {

  /**
   * A color for parking positions.
   */
  private static final Color C_PARK = Color.BLUE;
  /**
   * A color for report positions.
   */
  private static final Color C_REPORT = Color.WHITE;
  /**
   * A color for halt positions.
   */
  private static final Color C_HALT = Color.LIGHT_GRAY;
  /**
   * The figure's diameter in drawing units (pixels at 100% zoom).
   */
  private final int fDiameter;
  /**
   * The drawing options.
   */
  private final DrawingOptions drawingOptions;

  /**
   * Creates a new instance.
   *
   * @param model The model corresponding to this graphical object.
   * @param drawingOptions The drawing options.
   */
  @Inject
  public PointFigure(@Assisted PointModel model,
                     DrawingOptions drawingOptions) {
    super(model);
    this.drawingOptions = requireNonNull(drawingOptions, "drawingOptions");

    fDiameter = 10;
    fDisplayBox = new Rectangle(fDiameter, fDiameter);
    fZoomPoint = new ZoomPoint(0.5 * fDiameter, 0.5 * fDiameter);
  }

  @Override
  public PointModel getModel() {
    return (PointModel) get(FigureConstants.MODEL);
  }

  public Point center() {
    return Geom.center(fDisplayBox);
  }

  public Ellipse2D.Double getShape() {
    Rectangle2D r2 = fDisplayBox.getBounds2D();
    Ellipse2D.Double shape = new Ellipse2D.Double(r2.getX(), r2.getY(), fDiameter - 1, fDiameter - 1);
    return shape;
  }

  @Override  // Figure
  public Rectangle2D.Double getBounds() {
    Rectangle2D r2 = fDisplayBox.getBounds2D();
    Rectangle2D.Double r2d = new Rectangle2D.Double();
    r2d.setRect(r2);

    return r2d;
  }

  @Override  // Figure
  public Object getTransformRestoreData() {
    // Never used?
    return fDisplayBox.clone();
  }

  @Override  // Figure
  public void restoreTransformTo(Object restoreData) {
    // Never used?
    Rectangle r = (Rectangle) restoreData;
    fDisplayBox.x = r.x;
    fDisplayBox.y = r.y;
    fDisplayBox.width = r.width;
    fDisplayBox.height = r.height;
    fZoomPoint.setX(r.x + 0.5 * r.width);
    fZoomPoint.setY(r.y + 0.5 * r.height);
  }

  @Override  // Figure
  public void transform(AffineTransform tx) {
    Point2D center = getZoomPoint().getPixelLocationExactly();
    Point2D lead = new Point2D.Double();  // not used
    setBounds(
        (Point2D.Double) tx.transform(center, center),
        (Point2D.Double) tx.transform(lead, lead));
  }

  @Override  // AbstractFigure
  public void setBounds(Point2D.Double anchor, Point2D.Double lead) {
    fZoomPoint.setX(anchor.x);
    fZoomPoint.setY(anchor.y);
    fDisplayBox.x = (int) (anchor.x - 0.5 * fDiameter);
    fDisplayBox.y = (int) (anchor.y - 0.5 * fDiameter);
  }

  @Override
  protected void drawFigure(Graphics2D g) {
    if (drawingOptions.isBlocksVisible()) {
      drawBlockDecoration(g);
    }
    drawRouteDecoration(g);

    super.drawFigure(g);
  }

  private void drawRouteDecoration(Graphics2D g) {
    for (VehicleModel vehicleModel : getModel().getVehicleModels()) {
      Stroke stroke = Strokes.PATH_ON_ROUTE;
      Color color = transparentColor(vehicleModel.getDriveOrderColor(), 192);
      if (vehicleModel.getDriveOrderState() == TransportOrder.State.WITHDRAWN) {
        stroke = Strokes.PATH_ON_WITHDRAWN_ROUTE;
        color = Color.GRAY;
      }

      drawDecoration(g, stroke, color);
    }
  }

  private void drawBlockDecoration(Graphics2D g) {
    for (BlockModel blockModel : getModel().getBlockModels()) {
      drawDecoration(g, Strokes.BLOCK_ELEMENT, transparentColor(blockModel.getColor(), 192));
    }
  }

  private Color transparentColor(Color color, int alpha) {
    return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
  }

  private void drawDecoration(Graphics2D g, Stroke stroke, Color color) {
    g.setStroke(stroke);
    g.setColor(color);
    g.draw(this.getShape());
  }

  @Override  // AbstractAttributedFigure
  protected void drawFill(Graphics2D g) {
    Rectangle rect = fDisplayBox;

    if (getModel().getPropertyType().getValue() == PointModel.Type.PARK) {
      g.setColor(C_PARK);
    }
    else if (getModel().getPropertyType().getValue() == PointModel.Type.REPORT) {
      g.setColor(C_REPORT);
    }
    else {
      g.setColor(C_HALT);
    }

    if (rect.width > 0 && rect.height > 0) {
      g.fillOval(rect.x, rect.y, rect.width, rect.height);
    }

    if (getModel().getPropertyType().getValue() == PointModel.Type.PARK) {
      g.setColor(Color.white);
      Font oldFont = g.getFont();
      Font newFont = new Font(Font.DIALOG, Font.BOLD, 7);
      g.setFont(newFont);
      g.drawString("P", rect.x + 3, rect.y + rect.height - 3);
      g.setFont(oldFont);
    }
  }

  @Override  // AbstractAttributedFigure
  protected void drawStroke(Graphics2D g) {
    Rectangle r = fDisplayBox;

    if (r.width > 0 && r.height > 0) {
      g.drawOval(r.x, r.y, r.width - 1, r.height - 1);
    }
  }

  @Override // AbstractAttributedDecoratedFigure
  public PointFigure clone() {
    PointFigure thatFigure = (PointFigure) super.clone();
    thatFigure.setZoomPoint(new ZoomPoint(fZoomPoint.getX(), fZoomPoint.getY()));

    return thatFigure;
  }

  @Override // AbstractFigure
  public int getLayer() {
    return getModel().getPropertyLayerWrapper().getValue().getLayer().getOrdinal();
  }

  @Override
  public boolean isVisible() {
    return super.isVisible()
        && getModel().getPropertyLayerWrapper().getValue().getLayer().isVisible()
        && getModel().getPropertyLayerWrapper().getValue().getLayerGroup().isVisible();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/peripherals/PeripheralJobHistoryCodes.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.peripherals;

/**
 * Defines constants for basic history event codes related to peripheral jobs and documents how the
 * respective supplementary information is to be interpreted.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralJobHistoryCodes {

  /**
   * An event code indicating a peripheral job has been created.
   * <p>
   * The history entry's supplement is empty.
   * </p>
   */
  String JOB_CREATED = "tcsHistory:jobCreated";
  /**
   * An event code indicating a peripheral job was marked as being in a final state.
   * <p>
   * The history entry's supplement is empty.
   * </p>
   */
  String JOB_REACHED_FINAL_STATE = "tcsHistory:jobReachedFinalState";
}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/main/java/org/opentcs/guing/plugins/panels/statistics/VehicleStats.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.statistics;

/**
 * Statistics data for a vehicle.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class VehicleStats
    extends Stats {

  /**
   * The total time the vehicle was processing orders.
   */
  private long totalTimeProcessing;
  /**
   * When the vehicle last started processing an order.
   */
  private long lastProcessingStart;
  /**
   * The total time the vehicle was charging.
   */
  private long totalTimeCharging;
  /**
   * When the vehicle last started charging.
   */
  private long lastChargingStart;
  /**
   * The total time the vehicle was waiting.
   */
  private long totalTimeWaiting;
  /**
   * When the vehicle last started waiting.
   */
  private long lastWaitingStart;
  /**
   * The total number of orders the vehicle has processed.
   */
  private int totalOrdersProcessed;

  /**
   * Creates a new instance.
   *
   * @param name The name of the order.
   * @param totalRuntime The total runtime recorded.
   */
  public VehicleStats(final String name, final long totalRuntime) {
    super(name, totalRuntime);
  }

  /**
   * Returns the total time the vehicle was processing orders.
   *
   * @return The total time the vehicle was processing orders.
   */
  public long getTotalTimeProcessing() {
    return totalTimeProcessing;
  }

  /**
   * Returns the total time the vehicle was charging.
   *
   * @return The total time the vehicle was charging.
   */
  public long getTotalTimeCharging() {
    return totalTimeCharging;
  }

  /**
   * Returns the total time the vehicle was waiting.
   *
   * @return The total time the vehicle was waiting.
   */
  public long getTotalTimeWaiting() {
    return totalTimeWaiting;
  }

  /**
   * Returns the total number of orders the vehicle has processed.
   *
   * @return The total number of orders the vehicle has processed.
   */
  public int getTotalOrdersProcessed() {
    return totalOrdersProcessed;
  }

  /**
   * Indicates the vehicle started processing an order at the given time.
   *
   * @param timestamp When the vehicle started processing an order.
   */
  public void startProcessingOrder(long timestamp) {
    assert timestamp > 0;
    totalOrdersProcessed++;
    lastProcessingStart = timestamp;
  }

  /**
   * Indicates the vehicle stopped processing an order at the given time.
   *
   * @param timestamp When the vehicle stopped processing an order.
   */
  public void stopProcessingOrder(long timestamp) {
    assert timestamp > 0;
    if (lastProcessingStart != 0) {
      totalTimeProcessing += timestamp - lastProcessingStart;
    }
    lastProcessingStart = 0;
  }

  /**
   * Indicates the vehicle started charging at the given time.
   *
   * @param timestamp When the vehicle started charging.
   */
  public void startCharging(long timestamp) {
    assert timestamp > 0;
    lastChargingStart = timestamp;
  }

  /**
   * Indicates the vehicle stopped charging at the given time.
   *
   * @param timestamp When the vehicle stopped charging.
   */
  public void stopCharging(long timestamp) {
    assert timestamp > 0;
    if (lastChargingStart != 0) {
      totalTimeCharging += timestamp - lastChargingStart;
    }
    lastChargingStart = 0;
  }

  /**
   * Indicates the vehicle started waiting at the given time.
   *
   * @param timestamp When the vehicle started waiting.
   */
  public void startWaiting(long timestamp) {
    assert timestamp > 0;
    lastWaitingStart = timestamp;
  }

  /**
   * Indicates the vehicle stopped waiting at the given time.
   *
   * @param timestamp When the vehicle stopped waiting.
   */
  public void stopWaiting(long timestamp) {
    assert timestamp > 0;
    if (lastWaitingStart != 0) {
      totalTimeWaiting += timestamp - lastWaitingStart;
    }
    lastWaitingStart = 0;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/OrderCategorySuggestions.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.util.Set;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * Implementations of this class provide suggestions for transport order categories.
 *
 * @author <NAME> (Fraunhofer IML)
 * @deprecated Use {@link OrderTypeSuggestions} instead.
 */
@Deprecated
@ScheduledApiChange(when = "5.0", details = "Will be removed.")
public interface OrderCategorySuggestions {

  /**
   * Returns a set of categories that can be assigned to a transport order.
   *
   * @return A set of categories that can be assigned to a transport order.
   */
  Set<String> getCategorySuggestions();
}


<|start_filename|>openTCS-Kernel-Extension-Statistics/src/guiceConfig/java/org/opentcs/kernel/extensions/statistics/StatisticsModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.statistics;

import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Configures the statistics extension.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatisticsModule
    extends KernelInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StatisticsModule.class);

  @Override
  protected void configure() {
    StatisticsCollectorConfiguration configuration
        = getConfigBindingProvider().get(StatisticsCollectorConfiguration.PREFIX,
                                         StatisticsCollectorConfiguration.class);
    if (!configuration.enable()) {
      LOG.info("Statistics disabled by configuration.");
      return;
    }

    bind(StatisticsCollectorConfiguration.class)
        .toInstance(configuration);
    extensionsBinderOperating().addBinding()
        .to(StatisticsCollector.class);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/OriginFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.LinkedList;
import org.jhotdraw.draw.AbstractAttributedFigure;
import org.jhotdraw.draw.AttributeKeys;
import org.jhotdraw.draw.handle.Handle;
import org.jhotdraw.geom.Geom;
import org.opentcs.guing.components.drawing.ZoomPoint;
import org.opentcs.guing.components.drawing.course.Origin;

/**
 * A Figure for the coordinate system's origin.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class OriginFigure
    extends AbstractAttributedFigure {

  /**
   * The enclosing rectangle.
   */
  protected final Rectangle fDisplayBox;
  /**
   * The width and height.
   */
  private final int fSideLength;
  /**
   * The origin's model.
   */
  private Origin fModel;
  /**
   * The exact position of the figure.
   */
  private final ZoomPoint fZoomPoint;

  /**
   * Creates a new instance.
   */
  public OriginFigure() {
    super();
    fSideLength = 20;
    fZoomPoint = new ZoomPoint(0.0, 0.0);
    fDisplayBox = new Rectangle(-fSideLength / 2, -fSideLength / 2,
                                fSideLength, fSideLength);
    set(AttributeKeys.STROKE_COLOR, Color.blue);
    setSelectable(false);
  }

  /**
   * Set's the origin's model.
   *
   * @param model The model.
   */
  public void setModel(Origin model) {
    fModel = model;
    getModel().setPosition(Geom.center(fDisplayBox));
  }

  /**
   * Returns the origin's model.
   *
   * @return The model.
   */
  public Origin getModel() {
    return fModel;
  }

  /**
   * Returns the exact position of the origin.
   *
   * @return The exact position of the origin.
   */
  public ZoomPoint getZoomPoint() {
    return fZoomPoint;
  }

  @Override
  public Rectangle2D.Double getBounds() {
    Rectangle2D r2 = fDisplayBox.getBounds2D();
    Rectangle2D.Double r2d = new Rectangle2D.Double();
    r2d.setRect(r2);

    return r2d;
  }

  @Override
  public boolean contains(Point2D.Double p) {
    Rectangle r = (Rectangle) fDisplayBox.clone();
    double grow = AttributeKeys.getPerpendicularHitGrowth(this);
    r.x -= grow;
    r.y -= grow;
    r.width += grow * 2;
    r.height += grow * 2;

    return r.contains(p);
  }

  @Override
  public Object getTransformRestoreData() {
    return fDisplayBox.clone();
  }

  @Override
  public void restoreTransformTo(Object restoreData) {
    Rectangle r = (Rectangle) restoreData;
    fDisplayBox.x = r.x;
    fDisplayBox.y = r.y;
    fDisplayBox.width = r.width;
    fDisplayBox.height = r.height;
    fZoomPoint.setX(r.x + 0.5 * r.width);
    fZoomPoint.setY(r.y + 0.5 * r.height);
  }

  @Override
  public void transform(AffineTransform tx) {
    Point2D center = getZoomPoint().getPixelLocationExactly();
    Point2D lead = new Point2D.Double();  // not used
    setBounds(
        (Point2D.Double) tx.transform(center, center),
        (Point2D.Double) tx.transform(lead, lead));
  }

  @Override
  public void changed() {
    super.changed();
    getModel().setPosition(Geom.center(fDisplayBox));
    getModel().notifyLocationChanged();
  }

  @Override
  public void setBounds(Point2D.Double anchor, Point2D.Double lead) {
    // Only change the position here, NOT the size!
    // Draw the center of the figure at the mouse cursor's position.
    fZoomPoint.setX(anchor.x);
    fZoomPoint.setY(anchor.y);
    fDisplayBox.x = (int) (anchor.x - 0.5 * fSideLength);
    fDisplayBox.y = (int) (anchor.y - 0.5 * fSideLength);
//    fDisplayBox.x = (int) (anchor.x);
//    fDisplayBox.y = (int) (anchor.y);
  }

  @Override
  public Collection<Handle> createHandles(int detailLevel) {
    // No handles for the origin figure.
    return new LinkedList<>();
  }

  @Override
  protected void drawFill(Graphics2D g) {
    // No filling for the origin's figure.
  }

  @Override
  protected void drawStroke(Graphics2D g) {
    // Outline: "Crosshair" with circle
    Rectangle r = (Rectangle) fDisplayBox.clone();

    if (r.width > 0 && r.height > 0) {
      g.drawLine(r.x + r.width / 2, r.y, r.x + r.width / 2, r.y + r.height);
      g.drawLine(r.x, r.y + r.height / 2, r.x + r.width, r.y + r.height / 2);
      r.grow(-4, -4);
      g.drawOval(r.x, r.y, r.width, r.height);
    }
  }

  @Override
  public int getLayer() {
    return FigureOrdinals.ORIGIN_FIGURE_ORDINAL;
  }
}


<|start_filename|>openTCS-Kernel-Extension-Statistics/src/main/java/org/opentcs/kernel/extensions/statistics/StatisticsCollectorConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.statistics;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Configuration entries for the statistics collector.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(StatisticsCollectorConfiguration.PREFIX)
public interface StatisticsCollectorConfiguration {

  String PREFIX = "statisticscollector";

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to enable the statistics collector.",
      orderKey = "0")
  boolean enable();
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/InternalQueryService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import javax.annotation.Nonnull;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.QueryResponder;

/**
 * Declares query-related methods not accessible to remote peers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface InternalQueryService
    extends QueryService {

  /**
   * Registers the given responder for handling queries of the given type.
   *
   * @param clazz The query type.
   * @param responder The responder to handle the queries.
   */
  void registerResponder(@Nonnull Class<? extends Query<?>> clazz,
                         @Nonnull QueryResponder responder);

  /**
   * Unregisters the responder for the given type.
   *
   * @param clazz The query type.
   */
  void unregisterResponder(@Nonnull Class<? extends Query<?>> clazz);
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/BlockModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import org.opentcs.data.model.visualization.ElementPropKeys;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.components.properties.type.BlockTypeProperty;
import org.opentcs.guing.components.properties.type.ColorProperty;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.SelectionProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.components.properties.type.StringSetProperty;
import org.opentcs.guing.event.BlockChangeEvent;
import org.opentcs.guing.event.BlockChangeListener;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SimpleFolder;

/**
 * A block area. Contains figure components that are part of this block
 * area.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class BlockModel
    extends SimpleFolder {

  public static final String TYPE = "Type";
  /**
   * Key for the elements property.
   */
  public static final String ELEMENTS = "blockElements";
  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * A list of change listeners for this object.
   */
  private List<BlockChangeListener> fListeners = new LinkedList<>();

  /**
   * Creates a new instance.
   */
  public BlockModel() {
    super("");
    createProperties();
  }

  @Override  // AbstractModelComponent
  public String getTreeViewName() {
    String treeViewName = getDescription() + " " + getName();

    return treeViewName;
  }

  @Override  // AbstractModelComponent
  public String getDescription() {
    return bundle.getString("blockModel.description");
  }

  @Override  // AbstractModelComponent
  public void propertiesChanged(AttributesChangeListener listener) {
    if (getPropertyColor().hasChanged()) {
      colorChanged();
    }

    super.propertiesChanged(listener);
  }

  /**
   * Returns the color of this block area.
   *
   * @return The color.
   */
  public Color getColor() {
    return getPropertyColor().getColor();
  }

  /**
   * Adds an element to this block area.
   *
   * @param model The component to add.
   */
  public void addCourseElement(ModelComponent model) {
    if (!contains(model)) {
      getChildComponents().add(model);
      String addedModelName = model.getName();
      if (!getPropertyElements().getItems().contains(addedModelName)) {
        getPropertyElements().addItem(addedModelName);
      }
    }
  }

  /**
   * Removes an element from this block area.
   *
   * @param model The component to remove.
   */
  public void removeCourseElement(ModelComponent model) {
    if (contains(model)) {
      remove(model);
      getPropertyElements().getItems().remove(model.getName());
    }
  }

  /**
   * Removes all elements in this block area.
   */
  public void removeAllCourseElements() {
    for (Object o : new ArrayList<>(getChildComponents())) {
      remove((ModelComponent) o);
    }
  }

  /**
   * Adds a listeners that gets informed when this block members change.
   *
   * @param listener The new listener.
   */
  public void addBlockChangeListener(BlockChangeListener listener) {
    if (fListeners == null) {
      fListeners = new ArrayList<>();
    }

    if (!fListeners.contains(listener)) {
      fListeners.add(listener);
    }
  }

  /**
   * Removes a listener.
   *
   * @param listener The listener to remove.
   */
  public void removeBlockChangeListener(BlockChangeListener listener) {
    fListeners.remove(listener);
  }

  /**
   * Informs all listeners that the block elements have changed.
   */
  public void courseElementsChanged() {
    for (BlockChangeListener listener : fListeners) {
      listener.courseElementsChanged(new BlockChangeEvent(this));
    }
  }

  /**
   * Informs all listeners that the color of this block has changed.
   */
  public void colorChanged() {
    for (BlockChangeListener listener : fListeners) {
      listener.colorChanged(new BlockChangeEvent(this));
    }
  }

  /**
   * Informs all listeners that this block was removed.
   */
  public void blockRemoved() {
    for (BlockChangeListener listener : new ArrayList<>(fListeners)) {
      listener.blockRemoved(new BlockChangeEvent(this));
    }
  }

  public ColorProperty getPropertyColor() {
    return (ColorProperty) getProperty(ElementPropKeys.BLOCK_COLOR);
  }

  @SuppressWarnings("unchecked")
  public SelectionProperty<Type> getPropertyType() {
    return (SelectionProperty<Type>) getProperty(TYPE);
  }

  public StringSetProperty getPropertyElements() {
    return (StringSetProperty) getProperty(ELEMENTS);
  }

  public KeyValueSetProperty getPropertyMiscellaneous() {
    return (KeyValueSetProperty) getProperty(MISCELLANEOUS);
  }

  private void createProperties() {
    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("blockModel.property_name.description"));
    pName.setHelptext(bundle.getString("blockModel.property_name.helptext"));
    setProperty(NAME, pName);

    ColorProperty pColor = new ColorProperty(this, Color.red);
    pColor.setDescription(bundle.getString("blockModel.property_color.description"));
    pColor.setHelptext(bundle.getString("blockModel.property_color.helptext"));
    setProperty(ElementPropKeys.BLOCK_COLOR, pColor);

    BlockTypeProperty pType = new BlockTypeProperty(this,
                                                    Arrays.asList(Type.values()),
                                                    Type.values()[0]);
    pType.setDescription(bundle.getString("blockModel.property_type.description"));
    pType.setHelptext(bundle.getString("blockModel.property_type.helptext"));
    pType.setCollectiveEditable(true);
    setProperty(TYPE, pType);

    StringSetProperty pElements = new StringSetProperty(this);
    pElements.setDescription(bundle.getString("blockModel.property_elements.description"));
    pElements.setHelptext(bundle.getString("blockModel.property_elements.helptext"));
    pElements.setModellingEditable(false);
    pElements.setOperatingEditable(false);
    setProperty(ELEMENTS, pElements);

    KeyValueSetProperty pMiscellaneous = new KeyValueSetProperty(this);
    pMiscellaneous.setDescription(bundle.getString("blockModel.property_miscellaneous.description"));
    pMiscellaneous.setHelptext(bundle.getString("blockModel.property_miscellaneous.helptext"));
    pMiscellaneous.setOperatingEditable(true);
    setProperty(MISCELLANEOUS, pMiscellaneous);
  }

  /**
   * The supported point types.
   */
  public enum Type {

    /**
     * Single vehicle only allowed.
     */
    SINGLE_VEHICLE_ONLY(ResourceBundle.getBundle(BUNDLE_PATH).getString("blockModel.type.singleVehicleOnly.description")),
    /**
     * Same direction only allowed.
     */
    SAME_DIRECTION_ONLY(ResourceBundle.getBundle(BUNDLE_PATH).getString("blockModel.type.sameDirectionOnly.description"));

    private final String description;

    private Type(String description) {
      this.description = requireNonNull(description, "description");
    }

    public String getDescription() {
      return description;
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/menubar/ViewToolBarsMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import javax.swing.Action;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewToolBarsMenu
    extends JMenu {

  private static final ResourceBundleUtil labelsMenu
      = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);
  private static final ResourceBundleUtil labelsToolbar
      = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH);

  public ViewToolBarsMenu(Collection<Action> viewActions) {
    super(labelsMenu.getString("viewToolBarsMenu.text"));
    requireNonNull(viewActions, "viewActions");

    JCheckBoxMenuItem checkBoxMenuItem;
    for (Action a : viewActions) {
      checkBoxMenuItem = new JCheckBoxMenuItem(a);
      add(checkBoxMenuItem);

      if (checkBoxMenuItem.getText().equals(labelsToolbar.getString("toolBarManager.toolbar_drawing.title"))) {
        checkBoxMenuItem.setEnabled(false); // "Draw"-Toolbar musn't be disabled.
      }
    }

  }

}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/Property.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

/**
 * Interface for properties.
 * Wraps a type into a property to be able to change a value without creating a new object.
 * The property object stays the same while the value changes.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface Property
    extends ModelAttribute,
            Cloneable {

  /**
   * Copies the value of the property into this property.
   *
   * @param property The property.
   */
  void copyFrom(Property property);

  /**
   * Returns a comparable represantation of the value of this property.
   *
   * @return A represantation to compare this property to other ones.
   */
  Object getComparableValue();

  /**
   * Creates a copy of this property.
   *
   * @return The cloned property.
   */
  Object clone();
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/Kernel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

/**
 * Declares the methods an openTCS kernel implements.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface Kernel {

  /**
   * The default name used for the empty model created on startup.
   */
  String DEFAULT_MODEL_NAME = "unnamed";

  /**
   * Returns the current state of the kernel.
   *
   * @return The current state of the kernel.
   * @throws CredentialsException If the calling client is not allowed to
   * execute this method.
   */
  State getState()
      throws CredentialsException;

  /**
   * Sets the current state of the kernel.
   * <p>
   * Note: This method should only be used internally by the Kernel application.
   * </p>
   *
   * @param newState The state the kernel is to be set to.
   * @throws IllegalArgumentException If setting the new state is not possible,
   * e.g. because a transition from the current to the new state is not allowed.
   * @throws CredentialsException If the calling client is not allowed to
   * execute this method.
   */
  void setState(State newState)
      throws IllegalArgumentException, CredentialsException;

  /**
   * The various states a kernel instance may be running in.
   */
  enum State {

    /**
     * The state in which the model/topology is created and parameters are set.
     */
    MODELLING,
    /**
     * The normal mode of operation in which transport orders may be accepted
     * and dispatched to vehicles.
     */
    OPERATING,
    /**
     * A transitional state the kernel is in while shutting down.
     */
    SHUTDOWN
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/MenuItemComponentsFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus;

import org.opentcs.guing.components.properties.type.CoordinateProperty;

/**
 * A factory for creating instances in relation to menu items.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface MenuItemComponentsFactory {

  /**
   * Creates a {@link LayoutToModelCoordinateUndoActivity} for the given coordinate property.
   *
   * @param property The property.
   * @return The {@link LayoutToModelCoordinateUndoActivity}.
   */
  LayoutToModelCoordinateUndoActivity createLayoutToModelCoordinateUndoActivity(
      CoordinateProperty property);

  /**
   * Creates a {@link ModelToLayoutCoordinateUndoActivity} for the given coordinate property.
   *
   * @param property The property.
   * @return The {@link ModelToLayoutCoordinateUndoActivity}.
   */
  ModelToLayoutCoordinateUndoActivity createModelToLayoutCoordinateUndoActivity(
      CoordinateProperty property);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/KernelStateTransitionEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

import java.io.Serializable;

/**
 * Emitted by/for kernel state changes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class KernelStateTransitionEvent
    implements Serializable {

  /**
   * The old state the kernel is leaving.
   */
  private final Kernel.State leftState;
  /**
   * The new state the kernel is in transition to.
   */
  private final Kernel.State enteredState;
  /**
   * Whether the transition to the entered state is finished or not.
   */
  private final boolean transitionFinished;

  /**
   * Creates a new TCSKernelStateEvent.
   *
   * @param leftState The previous state of the kernel.
   * @param enteredState The new state of the kernel.
   * @param transitionFinished Whether the transistion is finished, yet.
   */
  public KernelStateTransitionEvent(Kernel.State leftState,
                                    Kernel.State enteredState,
                                    boolean transitionFinished) {
    this.leftState = leftState;
    this.enteredState = enteredState;
    this.transitionFinished = transitionFinished;
  }

  /**
   * Returns the state the kernel is leaving.
   *
   * @return The state the kernel is leaving.
   */
  public Kernel.State getLeftState() {
    return leftState;
  }

  /**
   * Returns the state for which this event was generated.
   *
   * @return The state for which this event was generated.
   */
  public Kernel.State getEnteredState() {
    return enteredState;
  }

  /**
   * Returns <code>true</code> if, and only if, the transition to the new kernel
   * state is finished.
   *
   * @return <code>true</code> if, and only if, the transition to the new kernel
   * state is finished.
   */
  public boolean isTransitionFinished() {
    return transitionFinished;
  }

  @Override
  public String toString() {
    return getClass().getSimpleName()
        + '{'
        + "leftState=" + leftState
        + ", enteredState=" + enteredState
        + ", transitionFinished=" + transitionFinished
        + '}';
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/sequences/OrderSequencesContainer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.sequences;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.guing.event.KernelStateChangeEvent;
import org.opentcs.guing.event.OperationModeChangeEvent;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Maintains a set of all order sequences existing on the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderSequencesContainer
    implements Lifecycle,
               EventHandler {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(OrderSequencesContainer.class);
  /**
   * Event bus.
   */
  private final EventBus eventBus;
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * The order sequences.
   */
  private final Map<String, OrderSequence> orderSequences = new HashMap<>();
  /**
   * This container's listeners.
   */
  private final Set<OrderSequenceContainerListener> listeners = new HashSet<>();
  /**
   * Whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public OrderSequencesContainer(@ApplicationEventBus EventBus eventBus,
                                 SharedKernelServicePortalProvider portalProvider) {
    this.eventBus = requireNonNull(eventBus, "eventBus");
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventBus.subscribe(this);
    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventBus.unsubscribe(this);
    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof TCSObjectEvent) {
      handleObjectEvent((TCSObjectEvent) event);
    }
    else if (event instanceof OperationModeChangeEvent) {
      initSequences();
    }
    else if (event instanceof SystemModelTransitionEvent) {
      initSequences();
    }
    else if (event instanceof KernelStateChangeEvent) {
      initSequences();
    }
  }

  private void initSequences() {
    setOrderSequences(fetchSequencesIfOnline());
    listeners.forEach(listener -> listener.containerInitialized(orderSequences.values()));
  }

  private Set<OrderSequence> fetchSequencesIfOnline() {
    if (portalProvider.portalShared()) {
      try ( SharedKernelServicePortal sharedPortal = portalProvider.register()) {
        return sharedPortal.getPortal().getTransportOrderService()
            .fetchObjects(OrderSequence.class);
      }
      catch (KernelRuntimeException exc) {
        LOG.warn("Exception fetching order sequences", exc);
      }
    }

    return new HashSet<>();
  }

  public void addListener(OrderSequenceContainerListener listener) {
    listeners.add(listener);
  }

  public void removeListener(OrderSequenceContainerListener listener) {
    listeners.remove(listener);
  }

  public Collection<OrderSequence> getOrderSequences() {
    return orderSequences.values();
  }

  private void handleObjectEvent(TCSObjectEvent evt) {
    if (evt.getCurrentOrPreviousObjectState() instanceof OrderSequence) {
      switch (evt.getType()) {
        case OBJECT_CREATED:
          orderSequenceAdded((OrderSequence) evt.getCurrentOrPreviousObjectState());
          break;
        case OBJECT_MODIFIED:
          orderSequencesChanged((OrderSequence) evt.getCurrentOrPreviousObjectState());
          break;
        case OBJECT_REMOVED:
          orderSequenceRemoved((OrderSequence) evt.getCurrentOrPreviousObjectState());
          break;
        default:
          LOG.warn("Unhandled event type: {}", evt.getType());
      }
    }
  }

  private void orderSequenceAdded(OrderSequence seq) {
    orderSequences.put(seq.getName(), seq);
    listeners.forEach(listener -> listener.orderSequenceAdded(seq));
  }

  private void orderSequencesChanged(OrderSequence seq) {
    orderSequences.put(seq.getName(), seq);
    listeners.forEach(listener -> listener.orderSequenceUpdated(seq));
  }

  private void orderSequenceRemoved(OrderSequence seq) {
    orderSequences.remove(seq.getName());
    listeners.forEach(listener -> listener.orderSequenceRemoved(seq));
  }

  private void setOrderSequences(Set<OrderSequence> sequences) {
    orderSequences.clear();
    for (OrderSequence seq : sequences) {
      orderSequences.put(seq.getName(), seq);
    }
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/layer/LayersTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.I18nPlantOverviewOperating;

/**
 * A table model for layers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class LayersTableModel
    extends AbstractTableModel
    implements LayerChangeListener,
               LayerGroupChangeListener {

  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewOperating.LAYERS_PATH);
  /**
   * The number of the "Ordinal" column.
   */
  public static final int COLUMN_ORDINAL = 0;
  /**
   * The number of the "Visible" column.
   */
  public static final int COLUMN_VISIBLE = 1;
  /**
   * The number of the "Name" column.
   */
  public static final int COLUMN_NAME = 2;
  /**
   * The number of the "Group" column.
   */
  public static final int COLUMN_GROUP = 3;
  /**
   * The number of the "Group visible" column.
   */
  public static final int COLUMN_GROUP_VISIBLE = 4;
  /**
   * The column names.
   */
  private static final String[] COLUMN_NAMES = new String[]{
    BUNDLE.getString("layersTableModel.column_ordinal.headerText"),
    BUNDLE.getString("layersTableModel.column_visible.headerText"),
    BUNDLE.getString("layersTableModel.column_name.headerText"),
    BUNDLE.getString("layersTableModel.column_group.headerText"),
    BUNDLE.getString("layersTableModel.column_groupVisible.headerText")
  };
  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
    Integer.class,
    Boolean.class,
    String.class,
    LayerGroup.class,
    Boolean.class
  };
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer editor.
   */
  private final LayerEditor layerEditor;

  /**
   * Creates a new instance.
   *
   * @param modelManager The model manager.
   * @param layerEditor The layer editor.
   */
  public LayersTableModel(ModelManager modelManager,
                          LayerEditor layerEditor) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerEditor = requireNonNull(layerEditor, "layerEditor");
  }

  @Override
  public int getRowCount() {
    return getLayers().size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return null;
    }

    Layer entry = getLayers().get(rowIndex);
    switch (columnIndex) {
      case COLUMN_ORDINAL:
        return entry.getOrdinal();
      case COLUMN_VISIBLE:
        return entry.isVisible();
      case COLUMN_NAME:
        return entry.getName();
      case COLUMN_GROUP:
        return getLayerGroups().get(entry.getGroupId());
      case COLUMN_GROUP_VISIBLE:
        return getLayerGroups().get(entry.getGroupId()).isVisible();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case COLUMN_ORDINAL:
        return false;
      case COLUMN_VISIBLE:
        return true;
      case COLUMN_NAME:
        return false;
      case COLUMN_GROUP:
        return false;
      case COLUMN_GROUP_VISIBLE:
        return false;
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return;
    }

    if (aValue == null) {
      return;
    }

    Layer entry = getLayers().get(rowIndex);
    switch (columnIndex) {
      case COLUMN_ORDINAL:
        // Do nothing.
        break;
      case COLUMN_VISIBLE:
        layerEditor.setLayerVisible(entry.getId(), (boolean) aValue);
        break;
      case COLUMN_NAME:
        // Do nothing.
        break;
      case COLUMN_GROUP:
        // Do nothing.
        break;
      case COLUMN_GROUP_VISIBLE:
        // Do nothing.
        break;
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public void layersInitialized() {
    // Once the layers are initialized we want to redraw the entire table to avoid any 
    // display errors.
    executeOnEventDispatcherThread(() -> fireTableDataChanged());
  }

  @Override
  public void layersChanged() {
    // Update the entire table but don't use fireTableDataChanged() to preserve the current 
    // selection.
    executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
  }

  @Override
  public void layerAdded() {
  }

  @Override
  public void layerRemoved() {
  }

  @Override
  public void groupsInitialized() {
  }

  @Override
  public void groupsChanged() {
    // The visibility of a group, which we display as well, may have changed. Update the table.
    executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
  }

  @Override
  public void groupAdded() {
  }

  @Override
  public void groupRemoved() {
  }

  private List<Layer> getLayers() {
    return getLayerWrappers().values().stream()
        .map(wrapper -> wrapper.getLayer())
        .collect(Collectors.toList());
  }

  private Map<Integer, LayerWrapper> getLayerWrappers() {
    return modelManager.getModel().getLayoutModel().getPropertyLayerWrappers().getValue();
  }

  private Map<Integer, LayerGroup> getLayerGroups() {
    return modelManager.getModel().getLayoutModel().getPropertyLayerGroups().getValue();
  }

  /**
   * Ensures the given runnable is executed on the EDT.
   * If the runnable is already being called on the EDT, the runnable is executed immediately.
   * Otherwise it is scheduled for execution on the EDT.
   * <p>
   * Note: Deferring a runnable by scheduling it for execution on the EDT even though it would 
   * have already been executed on the EDT may lead to exceptions due to data inconsistency.
   * </p>
   *
   * @param runnable The runnable.
   */
  private void executeOnEventDispatcherThread(Runnable runnable) {
    if (SwingUtilities.isEventDispatchThread()) {
      runnable.run();
    }
    else {
      SwingUtilities.invokeLater(runnable);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/DriveOrderTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import static org.opentcs.guing.plugins.panels.loadgenerator.I18nPlantOverviewPanelLoadGenerator.BUNDLE_PATH;

/**
 * A table model for drive orders.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class DriveOrderTableModel
    extends AbstractTableModel {

  /**
   * This classe's bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * The column names.
   */
  private final String[] columnNames = new String[] {
    bundle.getString("driveOrderTableModel.column_location.headerText"),
    bundle.getString("driveOrderTableModel.column_operation.headerText")
  };
  /**
   * The column classes.
   */
  private final Class<?>[] columnClasses = new Class<?>[] {
    TCSObjectReference.class,
    String.class
  };
  /**
   * The actual content.
   */
  private final List<DriveOrderStructure> driveOrderDataList = new ArrayList<>();

  /**
   * Creates a new instance.
   *
   * @param driveOrders The actual list of drive orders.
   */
  public DriveOrderTableModel(List<DriveOrderStructure> driveOrders) {
    requireNonNull(driveOrders, "driveOrders");

    for (DriveOrderStructure curDOS : driveOrders) {
      driveOrderDataList.add(curDOS);
    }
  }

  /**
   * Creates a new instance.
   */
  public DriveOrderTableModel() {
  }

  @Override
  public int getRowCount() {
    return driveOrderDataList.size();
  }

  @Override
  public int getColumnCount() {
    return columnNames.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= driveOrderDataList.size()) {
      return null;
    }
    DriveOrderStructure data = driveOrderDataList.get(rowIndex);

    if (data == null) {
      return null;
    }
    switch (columnIndex) {
      case 0:
        if (data.getDriveOrderLocation() == null) {
          return null;
        }
        else {
          return data.getDriveOrderLocation().getName();
        }

      case 1:
        return data.getDriveOrderVehicleOperation();
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return columnNames[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return columnClasses[columnIndex];
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case 0:
        return true;
      case 1:
        return true;
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= driveOrderDataList.size()) {
      return;
    }
    DriveOrderStructure data = driveOrderDataList.get(rowIndex);
    if (aValue == null) {
      return;
    }
    switch (columnIndex) {
      case 0:
        data.setDriveOrderLocation((TCSObjectReference<Location>) aValue);
        break;
      case 1:
        data.setDriveOrderVehicleOperation((String) aValue);
        break;
      default:
        throw new IllegalArgumentException("Unhandled columnIndex: " + columnIndex);
    }
  }

  /**
   * Returns this model's complete content.
   *
   * @return This model's complete content. The result list is unmodifiable.
   */
  public List<DriveOrderStructure> getContent() {
    return Collections.unmodifiableList(driveOrderDataList);
  }

  /**
   * Returns the DriveOrderStructure at the given index.
   *
   * @param row Index which DriveOrderStructure shall be returned
   * @return The DriveOrderStructure
   */
  public DriveOrderStructure getDataAt(int row) {
    if (row < 0 || row >= driveOrderDataList.size()) {
      return null;
    }
    return driveOrderDataList.get(row);
  }

  /**
   * Adds drive order data to the end of the model/list.
   *
   * @param driveOrder The new drive order data
   */
  public void addData(DriveOrderStructure driveOrder) {
    requireNonNull(driveOrder, "driveOrder");

    driveOrderDataList.add(driveOrder);
    fireTableDataChanged();
  }

  /**
   * Removes the DriveOrderStructure at the given index.
   * Does nothing if <code>row</code> is not in scope.
   *
   * @param row Index which DriveOrderStructure shall be removed
   */
  public void removeData(int row) {
    if (row < 0 || row >= driveOrderDataList.size()) {
      return;
    }
    driveOrderDataList.remove(row);
    fireTableDataChanged();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/AbstractLayerGroupsTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.I18nPlantOverview;

/**
 * A table model for layer groups.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractLayerGroupsTableModel
    extends AbstractTableModel
    implements LayerGroupChangeListener {

  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverview.LAYERS_PATH);
  /**
   * The number of the "ID" column.
   */
  public static final int COLUMN_ID = 0;
  /**
   * The number of the "Name" column.
   */
  public static final int COLUMN_NAME = 1;
  /**
   * The number of the "Visible" column.
   */
  public static final int COLUMN_VISIBLE = 2;
  /**
   * The column names.
   */
  private static final String[] COLUMN_NAMES = new String[]{
    BUNDLE.getString("abstractLayerGroupsTableModel.column_id.headerText"),
    BUNDLE.getString("abstractLayerGroupsTableModel.column_name.headerText"),
    BUNDLE.getString("abstractLayerGroupsTableModel.column_visible.headerText")
  };
  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
    Integer.class,
    String.class,
    Boolean.class
  };
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer group editor.
   */
  private final LayerGroupEditor layerGroupEditor;

  /**
   * Creates a new instance.
   *
   * @param modelManager The model manager.
   * @param layerGroupEditor The layer group editor.
   */
  public AbstractLayerGroupsTableModel(ModelManager modelManager,
                                       LayerGroupEditor layerGroupEditor) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerGroupEditor = requireNonNull(layerGroupEditor, "layerGroupEditor");
  }

  @Override
  public int getRowCount() {
    return layerGroups().size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return null;
    }

    LayerGroup entry = layerGroups().get(rowIndex);
    switch (columnIndex) {
      case COLUMN_ID:
        return entry.getId();
      case COLUMN_NAME:
        return entry.getName();
      case COLUMN_VISIBLE:
        return entry.isVisible();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case COLUMN_ID:
        return false;
      case COLUMN_NAME:
        return isNameColumnEditable();
      case COLUMN_VISIBLE:
        return isVisibleColumnEditable();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return;
    }

    if (aValue == null) {
      return;
    }

    LayerGroup entry = layerGroups().get(rowIndex);
    switch (columnIndex) {
      case COLUMN_ID:
        // Do nothing.
        break;
      case COLUMN_NAME:
        layerGroupEditor.setGroupName(entry.getId(), aValue.toString());
        break;
      case COLUMN_VISIBLE:
        layerGroupEditor.setGroupVisible(entry.getId(), (boolean) aValue);
        break;
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  public LayerGroup getDataAt(int index) {
    return layerGroups().get(index);
  }

  protected abstract boolean isNameColumnEditable();

  protected abstract boolean isVisibleColumnEditable();

  private List<LayerGroup> layerGroups() {
    return getLayerGroups().values().stream().collect(Collectors.toList());
  }

  private Map<Integer, LayerGroup> getLayerGroups() {
    return modelManager.getModel().getLayoutModel().getPropertyLayerGroups().getValue();
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/draw/AlignAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 * Changed by IML to allow access to ResourceBundle.
 *
 *
 * @(#)AlignAction.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.application.action.draw;

import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import static javax.swing.Action.SMALL_ICON;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.action.AbstractSelectedAction;
import org.jhotdraw.draw.event.TransformEdit;
import org.jhotdraw.undo.CompositeEdit;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Aligns the selected figures.
 *
 * XXX - Fire edit events
 *
 * @author <NAME>
 */
public abstract class AlignAction
    extends AbstractSelectedAction {

  protected ResourceBundleUtil bundle
      = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH);

  /**
   * Creates a new instance.
   *
   * @param editor The drawing editor
   */
  public AlignAction(DrawingEditor editor) {
    super(editor);
    updateEnabledState();
  }

  @Override
  protected final void updateEnabledState() {
    if (getView() != null) {
      setEnabled(getView().isEnabled()
          && getView().getSelectionCount() > 1);
    }
    else {
      setEnabled(false);
    }
  }

  @Override
  public void actionPerformed(java.awt.event.ActionEvent e) {
    CompositeEdit edit = new CompositeEdit(bundle.getString("alignAction.undo.presentationName"));
    fireUndoableEditHappened(edit);
    alignFigures(getView().getSelectedFigures(), getSelectionBounds());
    fireUndoableEditHappened(edit);
  }

  protected abstract void alignFigures(Collection<?> selectedFigures,
                                       Rectangle2D.Double selectionBounds);

  /**
   * Returns the bounds of the selected figures.
   *
   * @return The bounds of the selected figures.
   */
  protected Rectangle2D.Double getSelectionBounds() {
    Rectangle2D.Double bounds = null;

    for (Figure f : getView().getSelectedFigures()) {
      if (bounds == null) {
        bounds = f.getBounds();
      }
      else {
        bounds.add(f.getBounds());
      }
    }

    return bounds;
  }

  public static class North
      extends AlignAction {

    public North(DrawingEditor editor) {
      super(editor);

      putValue(SHORT_DESCRIPTION, bundle.getString("alignAction.north.shortDescription"));
      putValue(SMALL_ICON, ImageDirectory.getImageIcon("/toolbar/align-vertical-top-2.png"));
    }

    @Override
    protected void alignFigures(Collection<?> selectedFigures, Rectangle2D.Double selectionBounds) {
      double y = selectionBounds.y;

      for (Figure f : getView().getSelectedFigures()) {
        if (f.isTransformable()) {
          f.willChange();
          Rectangle2D.Double b = f.getBounds();
          AffineTransform tx = new AffineTransform();
          tx.translate(0, y - b.y);
          f.transform(tx);
          f.changed();
          fireUndoableEditHappened(new TransformEdit(f, tx));
        }
      }
    }
  }

  public static class East
      extends AlignAction {

    public East(DrawingEditor editor) {
      super(editor);

      putValue(SHORT_DESCRIPTION, bundle.getString("alignAction.east.shortDescription"));
      putValue(SMALL_ICON, ImageDirectory.getImageIcon("/toolbar/align-horizontal-right-2.png"));
    }

    @Override
    protected void alignFigures(Collection<?> selectedFigures, Rectangle2D.Double selectionBounds) {
      double x = selectionBounds.x + selectionBounds.width;

      for (Figure f : getView().getSelectedFigures()) {
        if (f.isTransformable()) {
          f.willChange();
          Rectangle2D.Double b = f.getBounds();
          AffineTransform tx = new AffineTransform();
          tx.translate(x - b.x - b.width, 0);
          f.transform(tx);
          f.changed();
          fireUndoableEditHappened(new TransformEdit(f, tx));
        }
      }
    }
  }

  public static class West
      extends AlignAction {

    public West(DrawingEditor editor) {
      super(editor);

      putValue(SHORT_DESCRIPTION, bundle.getString("alignAction.west.shortDescription"));
      putValue(SMALL_ICON, ImageDirectory.getImageIcon("/toolbar/align-horizontal-left.png"));
    }

    @Override
    protected void alignFigures(Collection<?> selectedFigures, Rectangle2D.Double selectionBounds) {
      double x = selectionBounds.x;

      for (Figure f : getView().getSelectedFigures()) {
        if (f.isTransformable()) {
          f.willChange();
          Rectangle2D.Double b = f.getBounds();
          AffineTransform tx = new AffineTransform();
          tx.translate(x - b.x, 0);
          f.transform(tx);
          f.changed();
          fireUndoableEditHappened(new TransformEdit(f, tx));
        }
      }
    }
  }

  public static class South
      extends AlignAction {

    public South(DrawingEditor editor) {
      super(editor);

      putValue(SHORT_DESCRIPTION, bundle.getString("alignAction.south.shortDescription"));
      putValue(SMALL_ICON, ImageDirectory.getImageIcon("/toolbar/align-vertical-bottom-2.png"));
    }

    @Override
    protected void alignFigures(Collection<?> selectedFigures, Rectangle2D.Double selectionBounds) {
      double y = selectionBounds.y + selectionBounds.height;

      for (Figure f : getView().getSelectedFigures()) {
        if (f.isTransformable()) {
          f.willChange();
          Rectangle2D.Double b = f.getBounds();
          AffineTransform tx = new AffineTransform();
          tx.translate(0, y - b.y - b.height);
          f.transform(tx);
          f.changed();
          fireUndoableEditHappened(new TransformEdit(f, tx));
        }
      }
    }
  }

  public static class Vertical
      extends AlignAction {

    public Vertical(DrawingEditor editor) {
      super(editor);

      putValue(SHORT_DESCRIPTION, bundle.getString("alignAction.vertical.shortDescription"));
      putValue(SMALL_ICON, ImageDirectory.getImageIcon("/toolbar/align-vertical-center-2.png"));
    }

    @Override
    protected void alignFigures(Collection<?> selectedFigures, Rectangle2D.Double selectionBounds) {
      double y = selectionBounds.y + selectionBounds.height / 2;

      for (Figure f : getView().getSelectedFigures()) {
        if (f.isTransformable()) {
          f.willChange();
          Rectangle2D.Double b = f.getBounds();
          AffineTransform tx = new AffineTransform();
          tx.translate(0, y - b.y - b.height / 2);
          f.transform(tx);
          f.changed();
          fireUndoableEditHappened(new TransformEdit(f, tx));
        }
      }
    }
  }

  public static class Horizontal
      extends AlignAction {

    public Horizontal(DrawingEditor editor) {
      super(editor);

      putValue(SHORT_DESCRIPTION, bundle.getString("alignAction.horizontal.shortDescription"));
      putValue(SMALL_ICON, ImageDirectory.getImageIcon("/toolbar/align-horizontal-center-2.png"));
    }

    @Override
    protected void alignFigures(Collection<?> selectedFigures, Rectangle2D.Double selectionBounds) {
      double x = selectionBounds.x + selectionBounds.width / 2;

      for (Figure f : getView().getSelectedFigures()) {
        if (f.isTransformable()) {
          f.willChange();
          Rectangle2D.Double b = f.getBounds();
          AffineTransform tx = new AffineTransform();
          tx.translate(x - b.x - b.width / 2, 0);
          f.transform(tx);
          f.changed();
          fireUndoableEditHappened(new TransformEdit(f, tx));
        }
      }
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/Lifecycle.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components;

/**
 * Defines methods for controlling a generic component's lifecycle.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface Lifecycle {

  /**
   * (Re-)Initializes this component before it is being used.
   */
  void initialize();
  
  /**
   * Checks whether this component is initialized.
   *
   * @return <code>true</code> if, and only if, this component is initialized.
   */
  boolean isInitialized();

  /**
   * Terminates the instance and frees resources.
   */
  void terminate();
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/exchange/KernelEventFetcher.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange;

import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.KernelStateTransitionEvent;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.common.ClientConnectionMode;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.event.OperationModeChangeEvent;
import static org.opentcs.util.Assertions.checkInRange;
import org.opentcs.util.CyclicTask;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Periodically fetches events from the kernel, if connected, and publishes them via the local event
 * bus.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class KernelEventFetcher
    implements Lifecycle,
               EventHandler {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(KernelEventFetcher.class);
  /**
   * The time to wait between event fetches with the service portal (in ms).
   */
  private final long eventFetchInterval = 1;
  /**
   * The time to wait for events to arrive when fetching (in ms).
   */
  private final long eventFetchTimeout = 1000;
  /**
   * Where we send events and receive them from.
   */
  private final EventBus eventBus;
  /**
   * Provides a shared portal instance.
   */
  private final SharedKernelServicePortalProvider servicePortalProvider;
  /**
   * The shared portal
   */
  private SharedKernelServicePortal sharedServicePortal;
  /**
   * The portal.
   */
  private KernelServicePortal servicePortal;
  /**
   * The task fetching the service portal for new events.
   */
  private EventFetcherTask eventFetcherTask;
  /**
   * Whether this event hub is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param eventBus Where this instance sends events.
   * @param servicePortalProvider Provides a shared portal instance.
   */
  @Inject
  public KernelEventFetcher(@ApplicationEventBus EventBus eventBus,
                            SharedKernelServicePortalProvider servicePortalProvider) {
    this.eventBus = requireNonNull(eventBus, "eventBus");
    this.servicePortalProvider = requireNonNull(servicePortalProvider, "servicePortalProvider");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    LOG.info("Initializing...");
    eventBus.subscribe(this);

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    LOG.info("Terminating...");
    eventBus.unsubscribe(this);

    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof OperationModeChangeEvent) {
      handleOperationModeChange((OperationModeChangeEvent) event);
    }
  }

  private void handleOperationModeChange(OperationModeChangeEvent event) {
    if (event.getNewMode() == OperationMode.OPERATING) {
      handleKernelConnect();
    }
    else {
      handleKernelDisconnect();
    }
  }

  private void handleKernelConnect() {
    if (eventFetcherTask != null) {
      return;
    }
    sharedServicePortal = servicePortalProvider.register();
    servicePortal = sharedServicePortal.getPortal();

    eventFetcherTask = new EventFetcherTask(eventFetchInterval, eventFetchTimeout);
    Thread eventFetcherThread = new Thread(eventFetcherTask, "KernelEventFetcher");
    eventFetcherThread.start();
  }

  private void handleKernelDisconnect() {
    if (eventFetcherTask == null) {
      return;
    }
    // Stop polling for events.
    eventFetcherTask.terminate();
    eventFetcherTask = null;

    sharedServicePortal.close();
    servicePortal = null;
  }

  /**
   * A task fetching the service portal for events in regular intervals.
   */
  private class EventFetcherTask
      extends CyclicTask {

    /**
     * The poll timeout.
     */
    private final long timeout;

    /**
     * Creates a new instance.
     *
     * @param interval The time to wait between polls in ms.
     * @param timeout The timeout in ms for which to wait for events to arrive with each polling
     * call.
     */
    private EventFetcherTask(long interval, long timeout) {
      super(interval);
      this.timeout = checkInRange(timeout, 1, Long.MAX_VALUE, "timeout");
    }

    @Override
    protected void runActualTask() {
      boolean shutDown = false;
      try {
        LOG.debug("Fetching remote kernel for events");
        List<Object> events = servicePortal.fetchEvents(timeout);
        for (Object event : events) {
          LOG.debug("Processing fetched event: {}", event);
          // Forward received events to all registered listeners.
          eventBus.onEvent(event);

          // Check if the kernel notifies us about a state change.
          if (event instanceof KernelStateTransitionEvent) {
            KernelStateTransitionEvent stateEvent = (KernelStateTransitionEvent) event;
            // If the kernel switches to SHUTDOWN, remember to shut down.
            shutDown = stateEvent.getEnteredState() == Kernel.State.SHUTDOWN;
          }
        }
      }
      catch (KernelRuntimeException exc) {
        LOG.error("Exception fetching events, logging out", exc);
        // Remember the connection problem by shutting it down properly.
        shutDown = true;
      }

      if (shutDown) {
        eventBus.onEvent(ClientConnectionMode.OFFLINE);
      }
    }
  }
}


<|start_filename|>openTCS-API-Base/src/test/java/org/opentcs/data/order/OrderSerializationTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.order;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;

/**
 * Tests for proper serialization and deserialization for TransportOrder and OrderSequence
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderSerializationTest {

  public OrderSerializationTest() {
  }

  @Test
  public void shouldSerializeAndDeserializeTransportOrder()
      throws Exception {
    TransportOrder originalObject = createTransportOrder();
    TransportOrder deserializedObject = (TransportOrder) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
    assertEquals(originalObject.getProperties(), deserializedObject.getProperties());
    assertTrue(originalObject.getAllDriveOrders().get(0).getDestination()
        .equals(deserializedObject.getAllDriveOrders().get(0).getDestination()));
  }

  @Test
  public void shouldSerializeAndDeserializeOrderSequence()
      throws Exception {
    OrderSequence originalObject = createOrderSequence();
    OrderSequence deserializedObject = (OrderSequence) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
    assertTrue(originalObject.getOrders().get(0)
        .equals(deserializedObject.getOrders().get(0)));
  }

  private TransportOrder createTransportOrder() {
    List<DriveOrder> driveOrders = new ArrayList<>();
    @SuppressWarnings("unchecked")
    Location location1 = new Location("Location1", mock(TCSObjectReference.class));
    @SuppressWarnings("unchecked")
    Location location2 = new Location("Location2", mock(TCSObjectReference.class));
    driveOrders.add(new DriveOrder(new DriveOrder.Destination(location1.getReference())
        .withOperation("someOperation1")));
    driveOrders.add(new DriveOrder(new DriveOrder.Destination(location2.getReference())
        .withOperation("someOperation2")));
    TransportOrder transportOrder = new TransportOrder("TransportOrder", driveOrders)
        .withProperty("someKey", "someValue");
    return transportOrder;
  }

  private OrderSequence createOrderSequence() {
    return new OrderSequence("OrderSequence")
        .withOrder(createTransportOrder().getReference());
  }

  private byte[] serializeTCSObject(TCSObject<?> tcsObject)
      throws IOException {
    byte[] serializedObject;
    try (ByteArrayOutputStream os = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(os)) {
      oos.writeObject(tcsObject);
      serializedObject = os.toByteArray();
    }

    return serializedObject;
  }

  private TCSObject<?> deserializeTCSObject(byte[] serializedObject)
      throws IOException, ClassNotFoundException {
    TCSObject<?> deserializedObject;
    try (ByteArrayInputStream is = new ByteArrayInputStream(serializedObject);
         ObjectInputStream ois = new ObjectInputStream(is)) {
      deserializedObject = (TCSObject) ois.readObject();
    }
    return deserializedObject;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/workingset/PrefixedUlidObjectNameProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.workingset;

import de.huxhorn.sulky.ulid.ULID;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import org.opentcs.access.to.CreationTO;
import org.opentcs.components.kernel.ObjectNameProvider;

/**
 * Provides names for objects based on ULIDs, prefixed with the name taken from a given
 * {@link CreationTO}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PrefixedUlidObjectNameProvider
    implements ObjectNameProvider {

  /**
   * Generates ULIDs for us.
   */
  private final ULID ulid = new ULID();
  /**
   * The previously generated ULID value.
   */
  private ULID.Value previousUlid = ulid.nextValue();

  /**
   * Creates a new instance.
   */
  public PrefixedUlidObjectNameProvider() {
  }

  @Override
  public String apply(CreationTO to) {
    requireNonNull(to, "to");

    Optional<ULID.Value> newValue = ulid.nextStrictlyMonotonicValue(previousUlid);
    while (newValue.isEmpty()) {
      newValue = ulid.nextStrictlyMonotonicValue(previousUlid);
    }
    previousUlid = newValue.get();
    return to.getName() + newValue.get().toString();
  }
}


<|start_filename|>openTCS-Strategies-Default/src/guiceConfig/java/org/opentcs/strategies/basic/routing/DefaultRouterModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing;

import javax.inject.Singleton;
import org.opentcs.components.kernel.routing.GroupMapper;
import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.opentcs.strategies.basic.routing.edgeevaluator.EdgeEvaluatorComposite;
import org.opentcs.strategies.basic.routing.edgeevaluator.EdgeEvaluatorDistance;
import org.opentcs.strategies.basic.routing.edgeevaluator.EdgeEvaluatorExplicitProperties;
import org.opentcs.strategies.basic.routing.edgeevaluator.EdgeEvaluatorHops;
import org.opentcs.strategies.basic.routing.edgeevaluator.EdgeEvaluatorTravelTime;
import org.opentcs.strategies.basic.routing.edgeevaluator.ExplicitPropertiesConfiguration;
import org.opentcs.strategies.basic.routing.jgrapht.BellmanFordPointRouterFactory;
import org.opentcs.strategies.basic.routing.jgrapht.DefaultModelGraphMapper;
import org.opentcs.strategies.basic.routing.jgrapht.DijkstraPointRouterFactory;
import org.opentcs.strategies.basic.routing.jgrapht.FloydWarshallPointRouterFactory;
import org.opentcs.strategies.basic.routing.jgrapht.ModelGraphMapper;
import org.opentcs.strategies.basic.routing.jgrapht.ShortestPathConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Guice configuration for the default router.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultRouterModule
    extends KernelInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultRouterModule.class);

  @Override
  protected void configure() {
    configureRouterDependencies();
    bindRouter(DefaultRouter.class);
  }

  private void configureRouterDependencies() {
    bind(DefaultRouterConfiguration.class)
        .toInstance(getConfigBindingProvider().get(DefaultRouterConfiguration.PREFIX,
                                                   DefaultRouterConfiguration.class));

    ShortestPathConfiguration spConfiguration
        = getConfigBindingProvider().get(ShortestPathConfiguration.PREFIX,
                                         ShortestPathConfiguration.class);
    bind(ShortestPathConfiguration.class)
        .toInstance(spConfiguration);

    bind(ModelGraphMapper.class)
        .to(DefaultModelGraphMapper.class);

    switch (spConfiguration.algorithm()) {
      case DIJKSTRA:
        bind(PointRouterFactory.class)
            .to(DijkstraPointRouterFactory.class);
        break;
      case BELLMAN_FORD:
        bind(PointRouterFactory.class)
            .to(BellmanFordPointRouterFactory.class);
        break;
      case FLOYD_WARSHALL:
        bind(PointRouterFactory.class)
            .to(FloydWarshallPointRouterFactory.class);
        break;
      default:
        LOG.warn("Unhandled algorithm selected ({}), falling back to Dijkstra's algorithm.",
                 spConfiguration.algorithm());
        bind(PointRouterFactory.class)
            .to(DijkstraPointRouterFactory.class);
    }

    edgeEvaluatorBinder()
        .addBinding(EdgeEvaluatorDistance.CONFIGURATION_KEY)
        .to(EdgeEvaluatorDistance.class);
    edgeEvaluatorBinder()
        .addBinding(EdgeEvaluatorExplicitProperties.CONFIGURATION_KEY)
        .to(EdgeEvaluatorExplicitProperties.class);
    edgeEvaluatorBinder()
        .addBinding(EdgeEvaluatorHops.CONFIGURATION_KEY)
        .to(EdgeEvaluatorHops.class);
    edgeEvaluatorBinder()
        .addBinding(EdgeEvaluatorTravelTime.CONFIGURATION_KEY)
        .to(EdgeEvaluatorTravelTime.class);

    bind(EdgeEvaluatorComposite.class)
        .in(Singleton.class);

    bind(ExplicitPropertiesConfiguration.class)
        .toInstance(getConfigBindingProvider().get(ExplicitPropertiesConfiguration.PREFIX,
                                                   ExplicitPropertiesConfiguration.class));

    bind(DefaultRoutingGroupMapper.class)
        .in(Singleton.class);
    bind(GroupMapper.class)
        .to(DefaultRoutingGroupMapper.class);
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/ViewManagerModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import bibliothek.gui.dock.common.DefaultSingleCDockable;
import java.awt.event.FocusEvent;
import java.io.File;
import java.util.ArrayList;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.draw.DrawingView;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.guing.components.dockable.CStackDockStation;
import org.opentcs.guing.components.dockable.DockingManagerModeling;
import org.opentcs.util.event.EventSource;

/**
 * Manages the mapping of dockables to drawing views, transport order views and
 * order sequence views.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewManagerModeling
    extends AbstractViewManager {

  /**
   * Manages the application's docking frames.
   */
  private final DockingManagerModeling dockingManager;
  /**
   * The default modelling dockable.
   */
  private DefaultSingleCDockable drawingViewModellingDockable;

  /**
   * Creates a new instance.
   *
   * @param dockingManager Manages the application's docking frames.
   * @param eventSource Where this instance registers event listeners.
   */
  @Inject
  public ViewManagerModeling(DockingManagerModeling dockingManager,
                             @ApplicationEventBus EventSource eventSource) {
    super(eventSource);
    this.dockingManager = requireNonNull(dockingManager, "dockingManager");
  }

  public void init() {
    setPlantOverviewStateModelling();
  }

  /**
   * Resets all components.
   */
  @Override
  public void reset() {
    super.reset();
    drawingViewModellingDockable = null;
  }

  /**
   * Initializes the unique modelling dockable.
   *
   * @param dockable The dockable that will be the modelling dockable.
   * @param title The title of this dockable.
   */
  public void initModellingDockable(DefaultSingleCDockable dockable, String title) {
    drawingViewModellingDockable = requireNonNull(dockable, "dockable");
    drawingViewModellingDockable.setTitleText(requireNonNull(title, "title"));
    drawingViewModellingDockable.setCloseable(false);
  }

  public void setBitmapToModellingView(File file) {
    getDrawingViewMap().get(drawingViewModellingDockable).getDrawingView().addBackgroundBitmap(file);
  }

  /**
   * Sets visibility states of all dockables to modelling.
   */
  private void setPlantOverviewStateModelling() {
    CStackDockStation station
        = dockingManager.getTabPane(DockingManagerModeling.COURSE_TAB_PANE_ID).getStation();

    for (DefaultSingleCDockable dock : new ArrayList<>(getDrawingViewMap().keySet())) {
      if (dock != drawingViewModellingDockable) {
        // Setting it to closeable = false, so the ClosingListener
        // doesn't remove the dockable when it's closed
        dock.setCloseable(false);
        dockingManager.setDockableVisibility(dock.getUniqueId(), false);
      }
    }

    dockingManager.showDockable(station, drawingViewModellingDockable, 0);
    DrawingView view = getDrawingViewMap().get(drawingViewModellingDockable).getDrawingView();
    view.getComponent().dispatchEvent(new FocusEvent(view.getComponent(), FocusEvent.FOCUS_GAINED));
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/scheduling/modules/SingleVehicleBlockModuleTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.scheduling.modules;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.junit.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Block;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.strategies.basic.scheduling.ReservationPool;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SingleVehicleBlockModuleTest {

  /**
   * The module to test.
   */
  private final SingleVehicleBlockModule module;

  private final ReservationPool reservationPool;

  private final InternalPlantModelService plantModelService;

  public SingleVehicleBlockModuleTest() {
    reservationPool = mock(ReservationPool.class);
    plantModelService = mock(InternalPlantModelService.class);
    module = new SingleVehicleBlockModule(reservationPool, plantModelService, new Object());
  }

  @Before
  public void setUp() {
  }

  @After
  public void tearDown() {
  }

  @Test
  public void shouldAllowAllocatioForNonBlocks() {
    Scheduler.Client client = new SampleClient();
    ModelData model = new ModelData();

    when(plantModelService.fetchObjects(eq(Block.class), any())).thenReturn(new HashSet<>());
    assertTrue(module.mayAllocate(client, model.resourcesToAllocate));
  }

  @Test
  public void shouldAllowAllocationForUnoccupiedBlock() {
    Scheduler.Client client = new SampleClient();
    ModelData model = new ModelData();

    when(plantModelService.fetchObjects(eq(Block.class), any()))
        .thenReturn(new HashSet<>(Arrays.asList(model.getBlock())));
    when(plantModelService.expandResources(any())).thenReturn(model.getBlockResources());
    when(reservationPool.resourcesAvailableForUser(model.getBlockResources(), client))
        .thenReturn(true);
    assertTrue(module.mayAllocate(client, model.getResourcesToAllocate()));
  }

  @Test
  public void shouldDenyAllocationForOccupiedBlock() {
    Scheduler.Client client = new SampleClient();
    ModelData model = new ModelData();

    when(plantModelService.fetchObjects(eq(Block.class), any()))
        .thenReturn(new HashSet<>(Arrays.asList(model.getBlock())));
    when(plantModelService.expandResources(any())).thenReturn(model.getBlockResources());
    when(reservationPool.resourcesAvailableForUser(model.getBlockResources(), client))
        .thenReturn(false);
    assertFalse(module.mayAllocate(client, model.getResourcesToAllocate()));
  }

  private class ModelData {

    private final Set<TCSResource<?>> blockResources = new HashSet<>();
    private final Set<TCSResource<?>> resourcesToAllocate = new HashSet<>();
    private final Block block;

    public ModelData() {
      Point pointA = new Point("A");
      Point pointB = new Point("B");
      Point pointC = new Point("C");
      Path pathAB = new Path("A-B", pointA.getReference(), pointB.getReference());
      Path pathBC = new Path("B-C", pointB.getReference(), pointC.getReference());

      Set<TCSResourceReference<?>> resourceRefs = new HashSet<>();
      resourceRefs.add(pointB.getReference());
      resourceRefs.add(pointC.getReference());
      resourceRefs.add(pathAB.getReference());
      resourceRefs.add(pathBC.getReference());
      block = new Block("Block")
          .withMembers(resourceRefs)
          .withType(Block.Type.SINGLE_VEHICLE_ONLY);

      blockResources.add(pathAB);
      blockResources.add(pointB);
      blockResources.add(pathBC);
      blockResources.add(pointC);

      resourcesToAllocate.add(pathAB);
      resourcesToAllocate.add(pointB);
    }

    public Set<TCSResource<?>> getBlockResources() {
      return blockResources;
    }

    public Set<TCSResource<?>> getResourcesToAllocate() {
      return resourcesToAllocate;
    }

    public Block getBlock() {
      return block;
    }
  }

  private class SampleClient
      implements Scheduler.Client {

    @Override
    public String getId() {
      return "SampleClient";
    }

    @Override
    public boolean allocationSuccessful(
        Set<TCSResource<?>> resources) {
      return true;
    }

    @Override
    public void allocationFailed(
        Set<TCSResource<?>> resources) {
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/PeripheralCommAdapterRegistry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Location;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;
import static org.opentcs.util.Assertions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A registry for all peripheral communication adapters in the system.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralCommAdapterRegistry
    implements Lifecycle {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralCommAdapterRegistry.class);
  /**
   * The registered factories.
   */
  private final Map<PeripheralCommAdapterDescription, PeripheralCommAdapterFactory> factories
      = new HashMap<>();
  /**
   * Indicates whether this component is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new registry.
   *
   * @param factories The peripheral comm adapter factories.
   */
  @Inject
  public PeripheralCommAdapterRegistry(Set<PeripheralCommAdapterFactory> factories) {
    requireNonNull(factories, "factories");
    for (PeripheralCommAdapterFactory factory : factories) {
      LOG.info("Setting up peripheral communication adapter factory: {}",
               factory.getClass().getName());
      this.factories.put(factory.getDescription(), factory);
    }
  }

  @Override
  public void initialize() {
    if (initialized) {
      return;
    }

    for (PeripheralCommAdapterFactory factory : factories.values()) {
      factory.initialize();
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!initialized) {
      return;
    }

    for (PeripheralCommAdapterFactory factory : factories.values()) {
      factory.terminate();
    }

    initialized = false;
  }

  /**
   * Returns all registered factories that can provide peripheral communication adapters.
   *
   * @return All registered factories that can provide peripheral communication adapters.
   */
  public List<PeripheralCommAdapterFactory> getFactories() {
    return new LinkedList<>(factories.values());
  }

  /**
   * Returns the factory for the given description.
   *
   * @param description The description to get the factory for.
   * @return The factory for the given description.
   */
  @Nonnull
  public PeripheralCommAdapterFactory findFactoryFor(
      @Nonnull PeripheralCommAdapterDescription description) {
    requireNonNull(description, "description");
    checkArgument(factories.get(description) != null,
                  "No factory for description %s",
                  description);

    return factories.get(description);
  }

  /**
   * Returns a set of factories that can provide communication adapters for the given location.
   *
   * @param location The location to find communication adapters/factories for.
   * @return A set of factories that can provide communication adapters for the given location.
   */
  public List<PeripheralCommAdapterFactory> findFactoriesFor(Location location) {
    requireNonNull(location, "location");

    return factories.values().stream()
        .filter(factory -> factory.providesAdapterFor(location))
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/factories/SecureSslContextFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.factories;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import static java.util.Objects.requireNonNull;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.opentcs.access.SslParameterSet;

/**
 * Provides methods for creating client-side and server-side {@link SSLContext} instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class SecureSslContextFactory
    implements Serializable {

  /**
   * The name of the algorithm to use for the {@link KeyManagerFactory} and
   * {@link TrustManagerFactory}.
   */
  private static final String KEY_TRUST_MANAGEMENT_ALGORITHM = "SunX509";
  /**
   * The protocol to use with the ssl context.
   */
  private static final String SSL_CONTEXT_PROTOCOL = "TLSv1.2";
  /**
   * The ssl parameters to be used for creating the ssl context.
   */
  private final SslParameterSet sslParameterSet;

  /**
   * Creates a new instance.
   *
   * @param sslParameterSet The ssl parameters to be used for creating the ssl context.
   */
  public SecureSslContextFactory(SslParameterSet sslParameterSet) {
    this.sslParameterSet = requireNonNull(sslParameterSet, "sslParameterSet");
  }

  /**
   * Creates an instance of {@link SSLContext} for the client.
   *
   * @return The ssl context.
   * @throws IllegalStateException If the creation of the ssl context fails.
   */
  public SSLContext createClientContext()
      throws IllegalStateException {
    SSLContext context = null;

    try {
      KeyStore ts = KeyStore.getInstance(sslParameterSet.getKeystoreType());
      ts.load(new FileInputStream(sslParameterSet.getTruststoreFile()),
              sslParameterSet.getTruststorePassword().toCharArray());
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(KEY_TRUST_MANAGEMENT_ALGORITHM);
      tmf.init(ts);

      context = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL);
      context.init(null, tmf.getTrustManagers(), null);
    }
    catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
               | KeyManagementException ex) {
      throw new IllegalStateException("Error creating the client's ssl context", ex);
    }

    return context;
  }

  /**
   * Creates an instance of {@link SSLContext} for the server.
   *
   * @return The ssl context.
   * @throws IllegalStateException If the creation of the ssl context fails.
   */
  public SSLContext createServerContext()
      throws IllegalStateException {
    SSLContext context = null;

    try {
      KeyStore ks = KeyStore.getInstance(sslParameterSet.getKeystoreType());
      ks.load(new FileInputStream(sslParameterSet.getKeystoreFile()),
              sslParameterSet.getKeystorePassword().toCharArray());
      KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEY_TRUST_MANAGEMENT_ALGORITHM);
      kmf.init(ks, sslParameterSet.getKeystorePassword().toCharArray());

      context = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL);
      context.init(kmf.getKeyManagers(), null, null);

    }
    catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException
               | KeyManagementException | UnrecoverableKeyException ex) {
      throw new IllegalStateException("Error creating the server's ssl context", ex);
    }

    return context;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/AbstractAttributesContent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import javax.swing.JComponent;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;

/**
 * Base implementation for visualisation of model component properties.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class AbstractAttributesContent
    implements AttributesContent {

  /**
   * The model component to show the properties of.
   */
  protected ModelComponent fModel;
  /**
   * The undo manager.
   */
  protected UndoRedoManager fUndoRedoManager;
  /**
   * The swing component.
   */
  protected JComponent fComponent;

  /**
   * Creates a new instance of AbstractAttributesContent
   */
  public AbstractAttributesContent() {
  }

  @Override // AttributesContent
  public void setModel(ModelComponent model) {
    fModel = model;
  }

  @Override // AttributesContent
  public abstract void reset();

  @Override // AttributesContent
  public JComponent getComponent() {
    return fComponent;
  }

  @Override // AttributesContent
  public String getDescription() {
    return fModel.getDescription();
  }

  @Override // AttributesContent
  public void setup(UndoRedoManager undoManager) {
    fUndoRedoManager = undoManager;
    fComponent = createComponent();
  }

  /**
   * Creates the component.
   *
   * @return The created component.
   */
  protected abstract JComponent createComponent();
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/TCSLabelFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import org.jhotdraw.draw.LabelFigure;
import org.jhotdraw.draw.event.FigureEvent;
import org.opentcs.data.model.visualization.ElementPropKeys;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.model.ModelComponent;

/**
 * A label belonging to another {@code Figure} that shows the name of the affiliated object in the
 * kernel model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TCSLabelFigure
    extends LabelFigure {

  /**
   * The default x label offset for label figures.
   */
  public static final int DEFAULT_LABEL_OFFSET_X = -10;

  /**
   * The default y label offset for label figures.
   */
  public static final int DEFAULT_LABEL_OFFSET_Y = -20;

  private Point2D.Double fOffset;
  private LabeledFigure fParent;
  private boolean isLabelVisible = true;

  /**
   * Creates a new instance.
   */
  public TCSLabelFigure() {
    this("?");
  }

  /**
   * Creates a new instance.
   *
   * @param text The text of the label
   */
  public TCSLabelFigure(String text) {
    super(text);
    fOffset = new Point2D.Double(DEFAULT_LABEL_OFFSET_X, DEFAULT_LABEL_OFFSET_Y);
  }

  /**
   * Sets the visibility flag of the label.
   *
   * @param visible The visibility flag.
   */
  public void setLabelVisible(boolean visible) {
    isLabelVisible = visible;

    if (visible) {
      setText(fParent.getPresentationFigure().getModel().getName());
    }
    else {
      setText("");
    }

    invalidate();
    validate();
  }

  /**
   * Sets the position relative to the {@code Figure}.
   *
   * @param posX The X-Offset of the label.
   * @param posY The Y-Offset of the label.
   */
  public void setOffset(int posX, int posY) {
    fOffset =  new Point2D.Double(posX, posY);
  }

  public Double getOffset() {
    return fOffset;
  }

  void setParent(LabeledFigure parent) {
    fParent = parent;
  }

  @Override  // AbstractFigure
  public void changed() {
    // Called when the figure has changed - movement with MouseDragger.
    super.changed();

    if (fParent != null) {
      TCSFigure figure = fParent.getPresentationFigure();
      ModelComponent model = figure.getModel();

      Point2D.Double newOffset = new Point2D.Double(
          getBounds().getX() - figure.getBounds().x,
          getBounds().getY() - figure.getBounds().y);

      if (newOffset.x != fOffset.x || newOffset.y != fOffset.y) {
        fOffset = newOffset;
        StringProperty sp = (StringProperty) model.getProperty(ElementPropKeys.POINT_LABEL_OFFSET_X);

        if (sp != null) {
          sp.setText(String.format("%d", (long) newOffset.x));
          sp.markChanged();
        }

        sp = (StringProperty) model.getProperty(ElementPropKeys.POINT_LABEL_OFFSET_Y);

        if (sp != null) {
          sp.setText(String.format("%d", (long) newOffset.y));
          sp.markChanged();
        }
        model.propertiesChanged(fParent);
      }
    }
  }

  @Override // AbstractFigure
  public int getLayer() {
    return 1; // stay above other figures ?
  }

  @Override  // LabelFigure
  public void figureChanged(FigureEvent event) {
    if (event.getFigure() instanceof LabeledFigure) {
      LabeledFigure lf = (LabeledFigure) event.getFigure();
      TCSFigure figure = lf.getPresentationFigure();
      ModelComponent model = figure.getModel();
      String name = model.getName();
      setText(name);

      if (isLabelVisible) {
        invalidate();
        validate();
      }
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/draw/EditorColorChooserAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 * Changed by IML to allow access to ResourceBundle.
 *
 *
 * @(#)EditorColorChooserAction.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.application.action.draw;

import java.awt.Color;
import java.awt.Component;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JColorChooser;
import org.jhotdraw.draw.AttributeKey;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.action.EditorColorIcon;
import org.jhotdraw.draw.event.FigureSelectionEvent;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * EditorColorChooserAction.
 * <p>
 * The behavior for choosing the initial color of
 * the JColorChooser matches with
 * {@link EditorColorIcon }.
 *
 * @author <NAME>
 */
public class EditorColorChooserAction
    extends AttributeAction {

  protected AttributeKey<Color> key;

  /**
   * Creates a new instance.
   *
   * @param editor The drawing editor
   * @param key The attribute key
   * @param name The name
   * @param icon The icon
   * @param fixedAttributes The fixed attributes
   */
  public EditorColorChooserAction(DrawingEditor editor,
                                  AttributeKey<Color> key,
                                  String name,
                                  Icon icon,
                                  Map<AttributeKey, Object> fixedAttributes) {

    super(editor, fixedAttributes, name, icon);
    this.key = key;
    putValue(AbstractAction.NAME, name);
    putValue(Action.SHORT_DESCRIPTION, ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH)
             .getString("editorColorChooserAction.shortDescription"));
    putValue(AbstractAction.SMALL_ICON, icon);
    updateEnabledState();
  }

  @Override
  public void actionPerformed(java.awt.event.ActionEvent e) {
    Color initialColor = getInitialColor();
    ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH);
    Color chosenColor = JColorChooser.showDialog((Component) e.getSource(),
                                                 labels.getString("editorColorChooserAction.dialog_colorSelection.title"),
                                                 initialColor);

    if (chosenColor != null) {
      HashMap<AttributeKey, Object> attr = new HashMap<>(attributes);
      attr.put(key, chosenColor);
      applyAttributesTo(attr, getView().getSelectedFigures());
    }
  }

  public void selectionChanged(FigureSelectionEvent evt) {
    //setEnabled(getView().getSelectionCount() > 0);
  }

  protected Color getInitialColor() {
    Color initialColor = getEditor().getDefaultAttribute(key);

    if (initialColor == null) {
      initialColor = Color.red;
    }

    return initialColor;
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/ClientConnectionMode.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

/**
 * Defines the modes in which an application may be in.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public enum ClientConnectionMode {
  /**
   * The application SHOULD be connected/online.
   */
  ONLINE,
  /**
   * The application SHOULD be disconnected/offline.
   */
  OFFLINE
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/PropertyTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "value"})
public class PropertyTO {
  
  private String name = "";
  private String value = "";

  @XmlAttribute(required = true)
  public String getName() {
    return name;
  }

  public PropertyTO setName(@Nonnull String name) {
    this.name = requireNonNull(name, "name");
    return this;
  }

  @XmlAttribute(required = true)
  public String getValue() {
    return value;
  }

  public PropertyTO setValue(@Nonnull String value) {
    requireNonNull(value, "value");
    this.value = value;
    return this;
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/sequences/OrderSequenceContainerListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.sequences;

import java.util.Collection;
import org.opentcs.data.order.OrderSequence;

/**
 *
 * Listener for changes in the {@link OrderSequencesContainerPanel}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OrderSequenceContainerListener {

  /**
   * Notifies the listener that the container has been initialized.
   *
   * @param sequences The sequences the container has been initialized with.
   */
  void containerInitialized(Collection<OrderSequence> sequences);

  /**
   * Notifies the listener that an order sequence has been added.
   *
   * @param sequence The order sequence that has been added.
   */
  void orderSequenceAdded(OrderSequence sequence);

  /**
   * Notifies the listener that an order sequence has been updated.
   *
   * @param sequence The order sequence that has been updated.
   */
  void orderSequenceUpdated(OrderSequence sequence);

  /**
   * Notifies the listener that an order sequence has been removed.
   *
   * @param sequence The order sequence that has been removed.
   */
  void orderSequenceRemoved(OrderSequence sequence);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/ModelTransitionEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

import java.io.Serializable;

/**
 * Emitted when the kernel loads a model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelTransitionEvent
    implements Serializable {

  /**
   * The old model the kernel is leaving.
   */
  private final String oldModelName;
  /**
   * The new model the kernel is in transition to.
   */
  private final String newModelName;
  /**
   * Whether the content of the model actually changed with the transition.
   */
  private final boolean modelContentChanged;
  /**
   * Whether the transition to the entered state is finished or not.
   */
  private final boolean transitionFinished;

  /**
   * Creates a new TCSModelTransitionEvent.
   *
   * @param oldModelName The name of the previously loaded model.
   * @param newModelName The name of the new model.
   * @param modelContentChanged Whether the content of the model actually
   * changed with the transition.
   * @param transitionFinished Whether the transition to the new model is
   * finished, yet.
   */
  public ModelTransitionEvent(String oldModelName,
                              String newModelName,
                              boolean modelContentChanged,
                              boolean transitionFinished) {
    this.oldModelName = oldModelName;
    this.newModelName = newModelName;
    this.modelContentChanged = modelContentChanged;
    this.transitionFinished = transitionFinished;
  }

  /**
   * Returns the model name the kernel is leaving.
   *
   * @return The model the kernel is leaving.
   */
  public String getOldModelName() {
    return oldModelName;
  }

  /**
   * Returns the model for which this event was generated.
   *
   * @return The model for which this event was generated.
   */
  public String getNewModelName() {
    return newModelName;
  }

  /**
   * Returns <code>true</code> if, and only if, the content of the model
   * actually changed with the transition.
   *
   * @return <code>true</code> if, and only if, the content of the model
   * actually changed with the transition.
   */
  public boolean hasModelContentChanged() {
    return modelContentChanged;
  }

  /**
   * Returns <code>true</code> if, and only if, the transition to the new kernel
   * state is finished.
   *
   * @return <code>true</code> if, and only if, the transition to the new kernel
   * state is finished.
   */
  public boolean isTransitionFinished() {
    return transitionFinished;
  }

  @Override
  public String toString() {
    return getClass().getSimpleName()
        + '{'
        + "oldModelName=" + oldModelName
        + ", newModelName=" + newModelName
        + ", modelContentChanged=" + modelContentChanged
        + ", transitionFinished=" + transitionFinished
        + '}';
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/PeripheralOperationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import static java.util.Objects.requireNonNull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
public class PeripheralOperationTO
    extends PlantModelElementTO {

  private String locationName = "";
  private String executionTrigger = "";
  private boolean completionRequired;

  @XmlAttribute(required = true)
  public String getLocationName() {
    return locationName;
  }

  public PeripheralOperationTO setLocationName(String locationName) {
    this.locationName = requireNonNull(locationName, "locationName");
    return this;
  }

  @XmlAttribute(required = true)
  public String getExecutionTrigger() {
    return executionTrigger;
  }

  public PeripheralOperationTO setExecutionTrigger(String executionTrigger) {
    this.executionTrigger = requireNonNull(executionTrigger, "executionTrigger");
    return this;
  }

  @XmlAttribute(required = true)
  public boolean isCompletionRequired() {
    return completionRequired;
  }

  public PeripheralOperationTO setCompletionRequired(boolean completionRequired) {
    this.completionRequired = completionRequired;
    return this;
  }

}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/main/java/org/opentcs/guing/plugins/panels/statistics/StatisticsPanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.statistics;

import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.access.Kernel;
import org.opentcs.components.plantoverview.PluggablePanel;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import static org.opentcs.guing.plugins.panels.statistics.I18nPlantOverviewPanelStatistics.BUNDLE_PATH;

/**
 * Creates statistics panels.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatisticsPanelFactory
    implements PluggablePanelFactory {

  /**
   * This class's bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * A provider for the actual panels.
   */
  private final Provider<StatisticsPanel> panelProvider;

  /**
   * Creates a new instance.
   *
   * @param panelProvider A provider for the actual panels.
   */
  @Inject
  public StatisticsPanelFactory(Provider<StatisticsPanel> panelProvider) {
    this.panelProvider = requireNonNull(panelProvider, "panelProvider");
  }

  @Override
  public String getPanelDescription() {
    return bundle.getString("statisticsPanelFactory.panelDescription");
  }

  @Override
  public PluggablePanel createPanel(Kernel.State state) {
    return panelProvider.get();
  }

  @Override
  public boolean providesPanel(Kernel.State state) {
    return true;
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/statistics/package-info.java<|end_filename|>
/**
 * Utility classes collecting statistical data.
 */
package org.opentcs.util.statistics;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/TCSObjectReference.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;

/**
 * A transient reference to a {@link TCSObject}.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <E> The actual object class.
 */
public class TCSObjectReference<E extends TCSObject<E>>
    implements Serializable {

  /**
   * The referenced object's class.
   */
  private final Class<?> referentClass;
  /**
   * The referenced object's name.
   */
  private final String name;

  /**
   * Creates a new TCSObjectReference.
   *
   * @param referent The object this reference references.
   */
  protected TCSObjectReference(@Nonnull TCSObject<E> referent) {
    requireNonNull(referent, "newReferent");

    referentClass = referent.getClass();
    name = referent.getName();
  }

  private TCSObjectReference(@Nonnull Class<?> clazz, @Nonnull String newName) {
    name = requireNonNull(newName, "newName");
    referentClass = requireNonNull(clazz, "clazz");
  }

  /**
   * Returns the referenced object's class.
   *
   * @return The referenced object's class.
   */
  public Class<?> getReferentClass() {
    return referentClass;
  }

  /**
   * Returns the referenced object's name.
   *
   * @return The referenced object's name.
   */
  public final String getName() {
    return name;
  }

  @Override
  public boolean equals(Object otherObj) {
    if (otherObj instanceof TCSObjectReference) {
      TCSObjectReference<?> otherRef = (TCSObjectReference<?>) otherObj;
      return referentClass.equals(otherRef.referentClass) && name.equals(otherRef.name);
    }
    else {
      return false;
    }
  }

  @Override
  public int hashCode() {
    return name.hashCode();
  }

  @Override
  public String toString() {
    return "TCSObjectReference{"
        + "referentClass=" + referentClass
        + ", name=" + name
        + '}';
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/CheckNewOrdersPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;

/**
 * Checks for transport orders that are still in state RAW, and attempts to prepare them for
 * assignment.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CheckNewOrdersPhase
    implements Phase {

  /**
   * The object service
   */
  private final TCSObjectService objectService;
  /**
   * The Router instance calculating route costs.
   */
  private final Router router;
  private final TransportOrderUtil transportOrderUtil;
  /**
   * The dispatcher configuration.
   */
  private final DefaultDispatcherConfiguration configuration;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public CheckNewOrdersPhase(TCSObjectService objectService,
                             Router router,
                             TransportOrderUtil transportOrderUtil,
                             DefaultDispatcherConfiguration configuration) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.router = requireNonNull(router, "router");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    objectService.fetchObjects(TransportOrder.class, this::inRawState).stream()
        .forEach(order -> checkRawTransportOrder(order));
  }

  private void checkRawTransportOrder(TransportOrder order) {
    requireNonNull(order, "order");

    // Check if the transport order is routable.
    if (configuration.dismissUnroutableTransportOrders()
        && router.checkRoutability(order).isEmpty()) {
      transportOrderUtil.updateTransportOrderState(order.getReference(),
                                                   TransportOrder.State.UNROUTABLE);
      return;
    }
    transportOrderUtil.updateTransportOrderState(order.getReference(),
                                                 TransportOrder.State.ACTIVE);
    // The transport order has been activated - dispatch it.
    // Check if it has unfinished dependencies.
    if (!transportOrderUtil.hasUnfinishedDependencies(order)) {
      transportOrderUtil.updateTransportOrderState(order.getReference(),
                                                   TransportOrder.State.DISPATCHABLE);
    }
  }

  private boolean inRawState(TransportOrder order) {
    return order.hasState(TransportOrder.State.RAW);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/course/CoordinateSystem.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.course;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.io.Serializable;

/**
 * A strategy that can translate pixel coordinates to real coordinates.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface CoordinateSystem
    extends Serializable {

  /**
   * Translates the real coordinate into a pixel coordinate.
   *
   * @param refPointLocation The current position of the reference point.
   * @param realValue The real position to translate.
   * @param relationX The amount of mm for one pixel in the x axis.
   * @param relationY The amount of mm for one pixel in the y axis.
   * @return A point with the pixel coordinates.
   */
  Point2D toPixel(Point refPointLocation, Point2D realValue, double relationX, double relationY);

  /**
   * Translates the pixel coordinate into a real coordinate.
   *
   * @param refPointLocation The current position of the reference point.
   * @param pixelValue The pixel coordinate position to translate.
   * @param relationX The amount of mm for one pixel in the x axis.
   * @param relationY The amount of mm for one pixel in the y axis.
   * @return A point with the real position.
   */
  Point2D toReal(Point refPointLocation, Point pixelValue, double relationX, double relationY);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/BlockContext.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import java.util.Set;
import javax.inject.Inject;
import javax.swing.JPopupMenu;
import org.opentcs.guing.model.elements.BlockModel;

/**
 * Context for the block tree view.
 *
 * @author <NAME> (<EMAIL>)
 */
public class BlockContext
    implements UserObjectContext {

  /**
   * Creates a new instance.
   */
  @Inject
  public BlockContext() {
  }

  @Override
  public JPopupMenu getPopupMenu(Set<UserObject> selectedUserObjects) {
    JPopupMenu menu = new JPopupMenu();

    return menu;
  }

  @Override
  public boolean removed(UserObject userObject) {
    if (userObject.getParent() instanceof BlockModel) {
      BlockModel blockModel = (BlockModel) userObject.getParent();
      blockModel.removeCourseElement(userObject.getModelComponent());

      blockModel.courseElementsChanged();

      return true;
    }
    return false;
  }

  @Override
  public ContextType getType() {
    return ContextType.BLOCK;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/FigureOrdinals.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

/**
 * Defines fixed ordinals for some figures.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface FigureOrdinals {

  /**
   * The layer ordinal to be used for the origin figure.
   * Note: Be cautious with this value. The ordinal for the default layer is 0 . So a value
   * of -1 for the origin figure should be enough. We can't really use e.g. Integer.MIN_VALUE as
   * this leads to unexpected behavior and exceptions when moving layers in the Model Editor
   * application (probably caused by FigureLayerComparator).
   */
  int ORIGIN_FIGURE_ORDINAL = -1;
  /**
   * The layer ordinal to be used for vehicle figures.
   * Note: Be cautious with this value. We want vehicles to be on the uppermost layer. We can't
   * really use e.g. Integer.MAX_VALUE as this leads to unexpected behavior when showing/hiding
   * layers in the Operations Desk application (probably caused by FigureLayerComparator).
   */
  int VEHICLE_FIGURE_ORDINAL = 1000000;
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/OpenTCSDrawingView.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.Point;
import java.io.File;
import java.util.Set;
import javax.annotation.Nonnull;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.components.drawing.figures.BitmapFigure;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.util.event.EventHandler;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OpenTCSDrawingView
    extends DrawingView,
            EventHandler {

  boolean isLabelsVisible();

  void setLabelsVisible(boolean newValue);

  /**
   * Called when the drawing options have changed.
   */
  void drawingOptionsChanged();

  /**
   * Returns if a given point on the screen is contained in this drawing view.
   *
   * @param p The reference point on the screen.
   * @return Boolean if this point is contained.
   */
  boolean containsPointOnScreen(Point p);

  /**
   * Adds a background image to this drawing view.
   *
   * @param file The file with the image.
   */
  void addBackgroundBitmap(File file);

  /**
   * Adds a background image to this drawing view.
   *
   * @param bitmapFigure The figure containing the image.
   */
  void addBackgroundBitmap(BitmapFigure bitmapFigure);

  /**
   * Scales the view to a value so the whole model fits.
   */
  void zoomViewToWindow();

  /**
   * Sets the elements of the blocks.
   *
   * @param blocks A <code>ModelComponent</code> which childs must be <code>BlockModels</code>.
   */
  void setBlocks(ModelComponent blocks);

  /**
   * Shows or hides the current route of a vehicle.
   *
   * @param vehicle The vehicle
   * @param visible <code>true</code> to set it to visible, <code>false</code> otherwise.
   */
  void displayDriveOrders(VehicleModel vehicle, boolean visible);

  /**
   * Updates the figures of a block.
   *
   * @param block The block.
   */
  void updateBlock(BlockModel block);

  /**
   * Scrolls to the given figure. Normally called when the user clicks on a model component in the
   * TreeView and wants to see the corresponding figure.
   *
   * @param figure The figure to be scrolled to.
   */
  void scrollTo(Figure figure);

  /**
   * Fixes the view on the vehicle and marks it and its destination with a colored circle.
   *
   * @param model The vehicle model.
   */
  void followVehicle(@Nonnull final VehicleModel model);

  /**
   * Releases the view and stops following the current vehicle.
   */
  void stopFollowVehicle();

  /**
   * Deletes the given model components from the drawing view.
   *
   * @param components The components to delete.
   */
  void delete(Set<ModelComponent> components);
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/StandardRemoteDispatcherService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.access.rmi.services.RegistrationName;
import org.opentcs.access.rmi.services.RemoteDispatcherService;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is the standard implementation of the {@link RemoteDispatcherService} interface.
 * <p>
 * Upon creation, an instance of this class registers itself with the RMI registry by the name
 * {@link RegistrationName#REMOTE_DISPATCHER_SERVICE}.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardRemoteDispatcherService
    extends KernelRemoteService
    implements RemoteDispatcherService {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StandardRemoteDispatcherService.class);
  /**
   * The dispatcher service to invoke methods on.
   */
  private final DispatcherService dispatcherService;
  /**
   * The user manager.
   */
  private final UserManager userManager;
  /**
   * Provides configuration data.
   */
  private final RmiKernelInterfaceConfiguration configuration;
  /**
   * Provides socket factories used for RMI.
   */
  private final SocketFactoryProvider socketFactoryProvider;
  /**
   * Provides the registry with which this remote service registers.
   */
  private final RegistryProvider registryProvider;
  /**
   * Executes tasks modifying kernel data.
   */
  private final ExecutorService kernelExecutor;
  /**
   * The registry with which this remote service registers.
   */
  private Registry rmiRegistry;
  /**
   * Whether this remote service is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param dispatcherService The dispatcher service.
   * @param userManager The user manager.
   * @param configuration This class' configuration.
   * @param socketFactoryProvider The socket factory provider used for RMI.
   * @param registryProvider The provider for the registry with which this remote service registers.
   * @param kernelExecutor Executes tasks modifying kernel data.
   */
  @Inject
  public StandardRemoteDispatcherService(DispatcherService dispatcherService,
                                         UserManager userManager,
                                         RmiKernelInterfaceConfiguration configuration,
                                         SocketFactoryProvider socketFactoryProvider,
                                         RegistryProvider registryProvider,
                                         @KernelExecutor ExecutorService kernelExecutor) {
    this.dispatcherService = requireNonNull(dispatcherService, "dispatcherService");
    this.userManager = requireNonNull(userManager, "userManager");
    this.configuration = requireNonNull(configuration, "configuration");
    this.socketFactoryProvider = requireNonNull(socketFactoryProvider, "socketFactoryProvider");
    this.registryProvider = requireNonNull(registryProvider, "registryProvider");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    rmiRegistry = registryProvider.get();

    // Export this instance via RMI.
    try {
      LOG.debug("Exporting proxy...");
      UnicastRemoteObject.exportObject(this,
                                       configuration.remoteDispatcherServicePort(),
                                       socketFactoryProvider.getClientSocketFactory(),
                                       socketFactoryProvider.getServerSocketFactory());
      LOG.debug("Binding instance with RMI registry...");
      rmiRegistry.rebind(RegistrationName.REMOTE_DISPATCHER_SERVICE, this);
    }
    catch (RemoteException exc) {
      LOG.error("Could not export or bind with RMI registry", exc);
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    try {
      LOG.debug("Unbinding from RMI registry...");
      rmiRegistry.unbind(RegistrationName.REMOTE_DISPATCHER_SERVICE);
      LOG.debug("Unexporting RMI interface...");
      UnicastRemoteObject.unexportObject(this, true);
    }
    catch (RemoteException | NotBoundException exc) {
      LOG.warn("Exception shutting down RMI interface", exc);
    }

    initialized = false;
  }

  @Override
  public void dispatch(ClientID clientId) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_ORDER);

    try {
      kernelExecutor.submit(() -> dispatcherService.dispatch()).get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }

  @Override
  public void withdrawByVehicle(ClientID clientId,
                                TCSObjectReference<Vehicle> ref,
                                boolean immediateAbort) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_ORDER);

    try {
      kernelExecutor.submit(() -> dispatcherService.withdrawByVehicle(ref, immediateAbort))
          .get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }

  @Override
  public void withdrawByTransportOrder(ClientID clientId,
                                       TCSObjectReference<TransportOrder> ref,
                                       boolean immediateAbort) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_ORDER);

    try {
      kernelExecutor.submit(() -> dispatcherService.withdrawByTransportOrder(ref, immediateAbort))
          .get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/persistence/unified/UnifiedModelPersistor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence.unified;

import java.io.File;
import java.io.IOException;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.filechooser.FileFilter;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.guing.persistence.ModelFilePersistor;
import org.opentcs.util.persistence.ModelParser;

/**
 * Serializes the data kept in a {@link PlantModelCreationTO} to a xml file.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class UnifiedModelPersistor
    implements ModelFilePersistor {

  /**
   * The model parser.
   */
  private final ModelParser modelParser;

  /**
   * Create a new instance.
   */
  @Inject
  public UnifiedModelPersistor(ModelParser modelParser) {
    this.modelParser = requireNonNull(modelParser, "modelParser");
  }

  @Override
  public boolean serialize(PlantModelCreationTO model, File file)
      throws IOException {
    requireNonNull(model, "model");
    requireNonNull(file, "file");

    writeFile(model, file);

    return true;
  }

  @Override
  public FileFilter getDialogFileFilter() {
    return UnifiedModelConstants.DIALOG_FILE_FILTER;
  }

  private void writeFile(PlantModelCreationTO plantModel, File file)
      throws IOException {
    File outFile = file.getName().endsWith(UnifiedModelConstants.FILE_ENDING_XML)
        ? file
        : new File(file.getParentFile(),
                   file.getName() + "." + UnifiedModelConstants.FILE_ENDING_XML);

    modelParser.writeModel(plantModel, outFile);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/PointRouterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing;

import org.opentcs.data.model.Vehicle;

/**
 * Implementations of this interface construct point routers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PointRouterFactory {

  /**
   * Creates a point router for the given vehicle.
   *
   * @param vehicle The vehicle.
   * @return The point router.
   */
  PointRouter createPointRouter(Vehicle vehicle);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/Query.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import java.io.Serializable;

/**
 * Marks a query (parameter) object.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <T> The result type.
 */
public interface Query<T> {

  /**
   * A convenience class to be used as the result type for queries that do not return any result.
   */
  public static class Void
      implements Serializable {

  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/PeripheralInteractor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.drivers.vehicle.MovementCommand;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Manages interactions with peripheral devices that are to be performed before or after the
 * execution of movement commands.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralInteractor
    implements EventHandler,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralInteractor.class);
  /**
   * The reference to the vehicle that's interacting with peripheral devices.
   */
  private final TCSObjectReference<Vehicle> vehicleRef;
  /**
   * The peripheral job service to use.
   */
  private final PeripheralJobService peripheralJobService;
  /**
   * The peripheral dispatcher service to use.
   */
  private final PeripheralDispatcherService peripheralDispatcherService;
  /**
   * The event source to register with.
   */
  private final EventSource eventSource;
  /**
   * The peripheral interactions to be performed BEFORE the exexution of a movement command mapped
   * to the corresponding movement command.
   */
  private final Map<MovementCommand, PeripheralInteraction> preMovementInteractions
      = new HashMap<>();
  /**
   * The peripheral interactions to be performed AFTER the exexution of a movement command mapped
   * to the corresponding movement command.
   */
  private final Map<MovementCommand, PeripheralInteraction> postMovementInteractions
      = new HashMap<>();
  /**
   * Indicates whether this instance is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param vehicleRef The reference to the vehicle that's interacting with peripheral devices.
   * @param peripheralJobService The peripheral job service to use.
   * @param peripheralDispatcherService The peripheral dispatcher service to use.
   * @param eventSource The event source to register with.
   */
  @Inject
  public PeripheralInteractor(@Assisted @Nonnull TCSObjectReference<Vehicle> vehicleRef,
                              @Nonnull PeripheralJobService peripheralJobService,
                              @Nonnull PeripheralDispatcherService peripheralDispatcherService,
                              @Nonnull @ApplicationEventBus EventSource eventSource) {
    this.vehicleRef = requireNonNull(vehicleRef, "vehicleRef");
    this.peripheralJobService = requireNonNull(peripheralJobService, "peripheralJobService");
    this.peripheralDispatcherService = requireNonNull(peripheralDispatcherService,
                                                      "peripheralDispatcherService");
    this.eventSource = requireNonNull(eventSource, "eventSource");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventSource.subscribe(this);

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventSource.unsubscribe(this);

    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (!(event instanceof TCSObjectEvent)) {
      return;
    }

    TCSObjectEvent objectEvent = (TCSObjectEvent) event;
    if (objectEvent.getType() != TCSObjectEvent.Type.OBJECT_MODIFIED) {
      return;
    }

    if (objectEvent.getCurrentOrPreviousObjectState() instanceof PeripheralJob) {
      onPeripheralJobChange(objectEvent);
    }
  }

  /**
   * Prepares for peripheral interactions in the context of the given movement command by
   * determining the interactions that have to be performed before and after the movement command
   * is executed.
   *
   * @param movementCommand The movement command to prepare peripheral interactions for.
   */
  public void prepareInteractions(MovementCommand movementCommand) {
    Path path = movementCommand.getStep().getPath();
    if (path == null) {
      return;
    }

    Map<PeripheralOperation.ExecutionTrigger, List<PeripheralOperation>> operations
        = path.getPeripheralOperations().stream()
            .collect(Collectors.groupingBy(t -> t.getExecutionTrigger()));
    operations.computeIfAbsent(PeripheralOperation.ExecutionTrigger.BEFORE_MOVEMENT,
                               executionTrigger -> new ArrayList<>());
    operations.computeIfAbsent(PeripheralOperation.ExecutionTrigger.AFTER_MOVEMENT,
                               executionTrigger -> new ArrayList<>());
    String reservationToken = determineReservationToken();

    List<PeripheralOperation> preMovementOperations
        = operations.get(PeripheralOperation.ExecutionTrigger.BEFORE_MOVEMENT);
    if (!preMovementOperations.isEmpty()) {
      preMovementInteractions.put(movementCommand,
                                  new PeripheralInteraction(vehicleRef,
                                                            movementCommand,
                                                            preMovementOperations,
                                                            peripheralJobService,
                                                            reservationToken));
    }

    List<PeripheralOperation> postMovementOperations
        = operations.get(PeripheralOperation.ExecutionTrigger.AFTER_MOVEMENT);
    if (!postMovementOperations.isEmpty()) {
      postMovementInteractions.put(movementCommand,
                                   new PeripheralInteraction(vehicleRef,
                                                             movementCommand,
                                                             postMovementOperations,
                                                             peripheralJobService,
                                                             reservationToken));
    }
  }

  /**
   * Starts the peripheral interactions that have to be performed before the given movement command
   * is executed.
   *
   * @param movementCommand The movement command.
   * @param succeededCallback The callback that is executed if the interactions succeeds (i.e. once
   * all required interactions are finished).
   * @param failedCallback The callback that is executed if the interactions fails (i.e. if a
   * single interaction failed).
   */
  public void startPreMovementInteractions(@Nonnull MovementCommand movementCommand,
                                           @Nonnull Runnable succeededCallback,
                                           @Nonnull Runnable failedCallback) {
    requireNonNull(movementCommand, "movementCommand");
    requireNonNull(succeededCallback, "succeededCallback");
    requireNonNull(failedCallback, "failedCallback");
    if (!preMovementInteractions.containsKey(movementCommand)) {
      LOG.debug("{}: No interactions to be performed before movement to {}...",
                vehicleRef.getName(),
                movementCommand.getStep().getDestinationPoint().getName());
      succeededCallback.run();
      return;
    }

    LOG.debug("{}: There are interactions to be performed before movement to {}...",
              vehicleRef.getName(),
              movementCommand.getStep().getDestinationPoint().getName());
    preMovementInteractions.get(movementCommand).start(succeededCallback, failedCallback);

    // In case there are only operations with the completion required flag not set, the interaction
    // is immediately finished and we can remove it right away.
    if (preMovementInteractions.get(movementCommand).isFinished()) {
      preMovementInteractions.remove(movementCommand);
    }

    // Peripheral jobs have been created. Disptach them.
    peripheralDispatcherService.dispatch();
  }

  /**
   * Starts the peripheral interactions that have to be performed after the given movement command
   * is executed.
   *
   * @param movementCommand The movement command.
   * @param succeededCallback The callback that is executed if the interactions succeeds (i.e. once
   * all required interactions are finished).
   * @param failedCallback The callback that is executed if the interactions fails (i.e. if a
   * single interaction failed).
   */
  public void startPostMovementInteractions(@Nonnull MovementCommand movementCommand,
                                            @Nonnull Runnable succeededCallback,
                                            @Nonnull Runnable failedCallback) {
    requireNonNull(movementCommand, "movementCommand");
    requireNonNull(succeededCallback, "succeededCallback");
    requireNonNull(failedCallback, "failedCallback");
    if (!postMovementInteractions.containsKey(movementCommand)) {
      LOG.debug("{}: No interactions to be performed after movement to {}...",
                vehicleRef.getName(),
                movementCommand.getStep().getDestinationPoint().getName());
      succeededCallback.run();
      return;
    }

    LOG.debug("{}: There are interactions to be performed after movement to {}...",
              vehicleRef.getName(),
              movementCommand.getStep().getDestinationPoint().getName());
    postMovementInteractions.get(movementCommand).start(succeededCallback, failedCallback);

    // In case there are only operations with the completion required flag not set, the interaction
    // is immediately finished and we can remove it right away.
    if (postMovementInteractions.get(movementCommand).isFinished()) {
      postMovementInteractions.remove(movementCommand);
    }

    // Peripheral jobs have been created. Disptach them.
    peripheralDispatcherService.dispatch();
  }

  /**
   * Returns whether there are any required (pre or post movement) interactions that have not been
   * finished yet.
   * In case there's a required interaction that has failed (and therefore not finished), this
   * method returns {@code true}.
   *
   * @return Whether there are any required interactions that have not been finished yet.
   */
  public boolean isWaitingForMovementInteractionsToFinish() {
    return isWaitingForPreMovementInteractionsToFinish()
        || isWaitingForPostMovementInteractionsToFinish();
  }

  /**
   * Returns whether there are any required (pre movement) interactions that have not been finished
   * yet.
   * In case there's a required interaction that has failed (and therefore not finished), this
   * method returns {@code true}.
   *
   * @return Whether there are any required (pre movement) interactions that have not been finished
   * yet.
   */
  public boolean isWaitingForPreMovementInteractionsToFinish() {
    return !preMovementInteractions.values().stream()
        .filter(PeripheralInteraction::hasRequiredOperations)
        .allMatch(PeripheralInteraction::isFinished);
  }

  /**
   * Returns whether there are any required (post movement) interactions that have not been finished
   * yet.
   * In case there's a required interaction that has failed (and therefore not finished), this
   * method returns {@code true}.
   *
   * @return Whether there are any required (post movement) interactions that have not been finished
   * yet.
   */
  public boolean isWaitingForPostMovementInteractionsToFinish() {
    return !postMovementInteractions.values().stream()
        .filter(PeripheralInteraction::hasRequiredOperations)
        .allMatch(PeripheralInteraction::isFinished);
  }

  /**
   * Returns a list of required operations that are still to be completed mapped to the associated
   * movement command's destination point.
   *
   * @return A list of required operations that are still to be completed mapped to the associated
   * movement command's destination point.
   */
  public Map<String, List<PeripheralOperation>> pendingRequiredInteractionsByDestination() {
    return Stream.concat(preMovementInteractions.entrySet().stream(),
                         postMovementInteractions.entrySet().stream())
        .map(entry -> entry.getValue())
        .filter(interaction -> interaction.hasRequiredOperations())
        // We're working with two streams from two maps which can each contain the same keys.
        // Therefore we have to use the groupingBy collector and need to flat map each interaction's
        // pending required operations.
        .collect(
            Collectors.groupingBy(
                interact -> interact.getMovementCommand().getStep().getDestinationPoint().getName(),
                Collectors.flatMapping(
                    interaction -> interaction.getPendingRequiredOperations().stream(),
                    Collectors.toList()
                )
            )
        );
  }

  private void onPeripheralJobChange(TCSObjectEvent event) {
    PeripheralJob prevJobState = (PeripheralJob) event.getPreviousObjectState();
    PeripheralJob currJobState = (PeripheralJob) event.getCurrentObjectState();

    if (prevJobState.getState() != currJobState.getState()) {
      switch (currJobState.getState()) {
        case FINISHED:
          onPeripheralJobFinished(currJobState);
          break;
        case FAILED:
          onPeripheralJobFailed(currJobState);
          break;
        default: // Do nothing
      }
    }
  }

  private void onPeripheralJobFinished(PeripheralJob job) {
    Stream.concat(preMovementInteractions.values().stream(),
                  postMovementInteractions.values().stream())
        .forEach(interaction -> interaction.onPeripheralJobFinished(job));

    Set<MovementCommand> preMovementsPrepared = preMovementInteractions.entrySet().stream()
        .filter(entry -> entry.getValue().isFinished())
        .map(entry -> entry.getKey())
        .collect(Collectors.toSet());
    Set<MovementCommand> postMovementsPrepared = postMovementInteractions.entrySet().stream()
        .filter(entry -> entry.getValue().isFinished())
        .map(entry -> entry.getKey())
        .collect(Collectors.toSet());

    preMovementsPrepared.forEach(
        movementCommand -> preMovementInteractions.remove(movementCommand)
    );
    postMovementsPrepared.forEach(
        movementCommand -> postMovementInteractions.remove(movementCommand)
    );
  }

  private void onPeripheralJobFailed(PeripheralJob job) {
    Stream.concat(preMovementInteractions.values().stream(),
                  postMovementInteractions.values().stream())
        .forEach(interaction -> interaction.onPeripheralJobFailed(job));
  }

  /**
   * Clears the interactions.
   */
  public void clear() {
    preMovementInteractions.clear();
    postMovementInteractions.clear();
  }

  private String determineReservationToken() {
    Vehicle vehicle = peripheralJobService.fetchObject(Vehicle.class, vehicleRef);
    if (vehicle.getTransportOrder() != null) {
      TransportOrder transportOrder = peripheralJobService.fetchObject(TransportOrder.class,
                                                                       vehicle.getTransportOrder());
      if (transportOrder.getPeripheralReservationToken() != null) {
        return transportOrder.getPeripheralReservationToken();
      }
    }

    return vehicle.getName();
  }
}


<|start_filename|>openTCS-Strategies-Default/src/guiceConfig/java/org/opentcs/strategies/basic/scheduling/DefaultSchedulerModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.scheduling;

import com.google.inject.multibindings.Multibinder;
import javax.inject.Singleton;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.opentcs.strategies.basic.scheduling.modules.SameDirectionBlockModule;
import org.opentcs.strategies.basic.scheduling.modules.SingleVehicleBlockModule;

/**
 * Guice configuration for the default scheduler.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultSchedulerModule
    extends KernelInjectionModule {

  @Override
  protected void configure() {
    configureSchedulerDependencies();
    bindScheduler(DefaultScheduler.class);
  }

  private void configureSchedulerDependencies() {
    bind(ReservationPool.class).in(Singleton.class);

    Multibinder<Scheduler.Module> moduleBinder = schedulerModuleBinder();
    moduleBinder.addBinding().to(SingleVehicleBlockModule.class);
    moduleBinder.addBinding().to(SameDirectionBlockModule.class);
  }
}


<|start_filename|>openTCS-KernelControlCenter/src/guiceConfig/java/org/opentcs/kernelcontrolcenter/LoopbackCommAdapterPanelsModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter;

import org.opentcs.customizations.controlcenter.ControlCenterInjectionModule;
import org.opentcs.virtualvehicle.LoopbackCommAdapterPanelFactory;

/**
 * Registers the loopback adapter's panels.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackCommAdapterPanelsModule
    extends ControlCenterInjectionModule {

  // tag::documentation_createCommAdapterPanelsModule[]
  @Override
  protected void configure() {
    commAdapterPanelFactoryBinder().addBinding().to(LoopbackCommAdapterPanelFactory.class);
  }
  // end::documentation_createCommAdapterPanelsModule[]
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/toolbar/SelectionToolFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.toolbar;

import com.google.inject.assistedinject.Assisted;
import java.util.Collection;
import javax.swing.Action;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface SelectionToolFactory {

  MultipleSelectionTool createMultipleSelectionTool(
      @Assisted("drawingActions") Collection<Action> drawingActions,
      @Assisted("selectionActions") Collection<Action> selectionActions);
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/PlantModelElementTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlTransient
@XmlAccessorType(XmlAccessType.PROPERTY)
public class PlantModelElementTO {

  private String name = "";
  private List<PropertyTO> properties = new ArrayList<>();

  @XmlAttribute(required = true)
  public String getName() {
    return name;
  }

  public PlantModelElementTO setName(@Nonnull String name) {
    requireNonNull(name, "name");
    this.name = name;
    return this;
  }

  @XmlElement(name = "property")
  public List<PropertyTO> getProperties() {
    return properties;
  }

  public PlantModelElementTO setProperties(@Nonnull List<PropertyTO> properties) {
    requireNonNull(properties, "properties");
    this.properties = properties;
    return this;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/AbstractViewManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.intern.DefaultCommonDockable;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.opentcs.guing.components.dockable.DockableTitleComparator;
import org.opentcs.guing.components.drawing.DrawingViewScrollPane;
import org.opentcs.util.event.EventSource;

/**
 * Manages the mapping of dockables to drawing views, transport order views and
 * order sequence views.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractViewManager
    implements ViewManager {

  /**
   * Where we register event listeners.
   */
  private final EventSource eventSource;
  /**
   * Map for Dockable -> DrawingView + Rulers.
   */
  private final Map<DefaultSingleCDockable, DrawingViewScrollPane> drawingViewMap;

  /**
   * Creates a new instance.
   *
   * @param eventSource Where this instance registers event listeners.
   */
  public AbstractViewManager(EventSource eventSource) {
    this.eventSource = requireNonNull(eventSource, "eventSource");
    drawingViewMap = new TreeMap<>(new DockableTitleComparator());
  }

  @Override
  public Map<DefaultSingleCDockable, DrawingViewScrollPane> getDrawingViewMap() {
    return drawingViewMap;
  }

  /**
   * Returns the title texts of all drawing views.
   *
   * @return List of strings containing the names.
   */
  @Override
  public List<String> getDrawingViewNames() {
    return drawingViewMap.keySet().stream()
        .map(dock -> dock.getTitleText())
        .sorted()
        .collect(Collectors.toList());
  }

  /**
   * Forgets the given dockable.
   *
   * @param dockable The dockable.
   */
  @Override
  public void removeDockable(DefaultSingleCDockable dockable) {
    DrawingViewScrollPane scrollPane = drawingViewMap.remove(dockable);
    if (scrollPane != null) {
      eventSource.unsubscribe(scrollPane.getDrawingView());
    }
  }

  /**
   * Resets all components.
   */
  public void reset() {
    drawingViewMap.clear();
  }

  public int getNextDrawingViewIndex() {
    return nextAvailableIndex(drawingViewMap.keySet());
  }

  /**
   * Puts a scroll pane with a key dockable into the drawing view map.
   * The scroll pane has to contain the drawing view and both rulers.
   *
   * @param dockable The dockable the scrollPane is wrapped into. Used as the key.
   * @param scrollPane The scroll pane containing the drawing view and rulers.
   */
  public void addDrawingView(DefaultSingleCDockable dockable,
                             DrawingViewScrollPane scrollPane) {
    requireNonNull(dockable, "dockable");
    requireNonNull(scrollPane, "scrollPane");

    eventSource.subscribe(scrollPane.getDrawingView());
    drawingViewMap.put(dockable, scrollPane);
  }

  /**
   * Evaluates which dockable should be the front dockable.
   *
   * @return The dockable that should be the front dockable. <code>null</code>
   * if no dockables exist.
   */
  public DefaultCommonDockable evaluateFrontDockable() {
    if (!drawingViewMap.isEmpty()) {
      return drawingViewMap.keySet().iterator().next().intern();
    }
    return null;
  }

  /**
   * Returns the next available index of a set of dockables.
   * E.g. if "Dock 0" and "Dock 2" are being used, 1 would be returned.
   *
   * @param setToIterate The set to iterate.
   * @return The next available index.
   */
  protected int nextAvailableIndex(Set<DefaultSingleCDockable> setToIterate) {
    // Name
    Pattern p = Pattern.compile("\\d");
    Matcher m;
    int biggestIndex = 0;

    for (DefaultSingleCDockable dock : setToIterate) {
      m = p.matcher(dock.getTitleText());

      if (m.find()) {
        int index = Integer.parseInt(m.group(0));

        if (index > biggestIndex) {
          biggestIndex = index;
        }
      }
    }

    return biggestIndex + 1;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/action/view/AddPluginPanelAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.view;

import java.awt.event.ActionEvent;
import java.util.Objects;
import javax.swing.AbstractAction;
import javax.swing.JCheckBoxMenuItem;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import org.opentcs.guing.application.PluginPanelManager;

/**
 * An action to add a plugin panel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AddPluginPanelAction
    extends AbstractAction {

  public final static String ID = "view.addPluginPanel";
  private final PluggablePanelFactory factory;
  private final PluginPanelManager pluginPanelManager;

  /**
   * Creates a new instance.
   *
   * @param pluginPanelManager The openTCS view
   * @param factory The pluggable panel factory
   */
  public AddPluginPanelAction(PluginPanelManager pluginPanelManager, PluggablePanelFactory factory) {
    this.pluginPanelManager = Objects.requireNonNull(pluginPanelManager, "pluginPanelManager");
    this.factory = Objects.requireNonNull(factory, "panelID is null");
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    JCheckBoxMenuItem item = (JCheckBoxMenuItem) e.getSource();
    pluginPanelManager.showPluginPanel(factory, item.isSelected());
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/sequences/OrderSequencesContainerPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.sequences;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import javax.inject.Inject;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.RowFilter;
import org.opentcs.customizations.plantoverview.ApplicationFrame;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.guing.components.dialogs.DialogContent;
import org.opentcs.guing.components.dialogs.StandardContentDialog;
import org.opentcs.guing.transport.FilterButton;
import org.opentcs.guing.transport.FilteredRowSorter;
import org.opentcs.guing.transport.OrdersTable;
import org.opentcs.guing.transport.orders.TransportViewFactory;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.guing.util.IconToolkit;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Shows a table of the kernel's order sequences.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderSequencesContainerPanel
    extends JPanel {

  /**
   * The path to the icons.
   */
  private static final String ICON_PATH = "/org/opentcs/guing/res/symbols/panel/";
  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(OrderSequencesContainerPanel.class);
  /**
   * A factory for order sequence views.
   */
  private final TransportViewFactory transportViewFactory;
  /**
   * The parent component for dialogs shown by this instance.
   */
  private final Component dialogParent;
  /**
   * The table showing the order sequences.
   */
  private JTable fTable;
  /**
   * The table's model.
   */
  private OrderSequenceTableModel tableModel;
  /**
   * The sorter for the table.
   */
  private FilteredRowSorter<OrderSequenceTableModel> sorter;
  /**
   * Holds the order sequences.
   */
  private final OrderSequencesContainer orderSequencesContainer;

  /**
   * Creates a new instance.
   *
   * @param transportViewFactory A factory for order sequence views.
   * @param dialogParent The parent component for dialogs shown by this instance.
   * @param orderSequencesContainer Maintains a set of order sequences on the kernel side.
   */
  @Inject
  public OrderSequencesContainerPanel(TransportViewFactory transportViewFactory,
                                      @ApplicationFrame Component dialogParent,
                                      OrderSequencesContainer orderSequencesContainer) {
    this.transportViewFactory = requireNonNull(transportViewFactory, "transportViewFactory");
    this.dialogParent = requireNonNull(dialogParent, "dialogParent");
    this.orderSequencesContainer = requireNonNull(orderSequencesContainer,
                                                  "orderSequencesContainer");

    initComponents();
  }

  /**
   * Initializes this panel's contents.
   */
  public void initView() {
    tableModel.containerInitialized(orderSequencesContainer.getOrderSequences());
  }

  private void initComponents() {
    setLayout(new BorderLayout());

    tableModel = new OrderSequenceTableModel();
    orderSequencesContainer.addListener(tableModel);
    fTable = new OrdersTable(tableModel);

    sorter = new FilteredRowSorter<>(tableModel);
    // Prevent manual sorting.
    for (int i = 0; i < fTable.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    fTable.setRowSorter(sorter);

    JScrollPane scrollPane = new JScrollPane(fTable);
    add(scrollPane, BorderLayout.CENTER);

    JToolBar toolBar = createToolBar(createFilterButtons());
    add(toolBar, BorderLayout.NORTH);

    fTable.addMouseListener(new MouseAdapter() {

      @Override
      public void mouseClicked(MouseEvent evt) {
        if (evt.getButton() == MouseEvent.BUTTON1) {
          if (evt.getClickCount() == 2) {
            showOrderSequence();
          }
        }

        if (evt.getButton() == MouseEvent.BUTTON3) {
          showPopupMenu(evt.getX(), evt.getY());
        }
      }
    });
  }

  private void showOrderSequence() {
    getSelectedOrderSequence().ifPresent(os -> {
      DialogContent content = transportViewFactory.createOrderSequenceView(os);
      StandardContentDialog dialog
          = new StandardContentDialog(dialogParent, content, true, StandardContentDialog.CLOSE);
      dialog.setVisible(true);
    });
  }

  private void showPopupMenu(int x, int y) {
    int row = fTable.rowAtPoint(new Point(x, y));
    fTable.setRowSelectionInterval(row, row);

    JPopupMenu menu = new JPopupMenu();
    JMenuItem item = menu.add(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TO_SEQUENCE_PATH)
        .getString("orderSequencesContainerPanel.table_sequences.popupMenuItem_showDetails.text"));
    item.addActionListener((ActionEvent evt) -> showOrderSequence());

    menu.show(fTable, x, y);
  }

  private Optional<OrderSequence> getSelectedOrderSequence() {
    int row = fTable.getSelectedRow();

    if (row == -1) {
      return Optional.empty();
    }

    return Optional.of(tableModel.getEntryAt(fTable.convertRowIndexToModel(row)));
  }

  private List<FilterButton> createFilterButtons() {

    List<FilterButton> buttons = new LinkedList<>();

    FilterButton b1 = new FilterButton(
        IconToolkit.instance().getImageIconByFullPath(ICON_PATH + "filterFinished.16x16.gif"),
        createFilter(),
        sorter
    );
    buttons.add(b1);
    b1.setToolTipText(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TO_SEQUENCE_PATH)
        .getString("orderSequencesContainerPanel.button_filterFinishedOrderSequences.tooltipText"));

    return buttons;
  }

  private RowFilter<Object, Object> createFilter() {
    return new RowFilter<Object, Object>() {
      @Override
      public boolean include(Entry<? extends Object, ? extends Object> entry) {
        OrderSequence os = ((OrderSequenceTableModel) entry.getModel()).getEntryAt((int) entry.getIdentifier());
        return os.isComplete();
      }
    };
  }

  private JToolBar createToolBar(List<FilterButton> filterButtons) {
    JToolBar toolBar = new JToolBar();

    for (FilterButton button : filterButtons) {
      toolBar.add(button);
    }

    return toolBar;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/factories/package-info.java<|end_filename|>
/**
 * Interfaces and classes for configuration of the RMI runtime used by openTCS kernel and clients.
 */
package org.opentcs.access.rmi.factories;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/transportorder/TransportOrderComparatorDeadlineAtRiskFirst.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.transportorder;

import java.time.Instant;
import java.util.Comparator;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;

/**
 * Compares {@link TransportOrder}s by their deadlines, ordering those with a deadline at risk
 * first.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderComparatorDeadlineAtRiskFirst
    implements Comparator<TransportOrder> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "DEADLINE_AT_RISK_FIRST";

  /**
   * The time window (in ms) before its deadline in which an order becomes urgent.
   */
  private final long deadlineAtRiskPeriod;

  @Inject
  public TransportOrderComparatorDeadlineAtRiskFirst(DefaultDispatcherConfiguration configuration) {
    requireNonNull(configuration, "configuration");

    this.deadlineAtRiskPeriod = configuration.deadlineAtRiskPeriod();
  }

  /**
   * Compares two orders by their deadline's criticality.
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param order1 The first order.
   * @param order2 The second order.
   * @return the value 0 if the deadlines of order1 and order2 are both at risk or not,
   * a value less than 0 if only the deadline of order1 is at risk
   * and a value greater than 0 in all other cases.
   */
  @Override
  public int compare(TransportOrder order1, TransportOrder order2) {
    boolean order1AtRisk = deadlineAtRisk(order1);
    boolean order2AtRisk = deadlineAtRisk(order2);

    if (order1AtRisk == order2AtRisk) {
      return 0;
    }
    else if (order1AtRisk) {
      return -1;
    }
    else {
      return 1;
    }
  }

  private boolean deadlineAtRisk(TransportOrder order) {
    return order.getDeadline().minusMillis(deadlineAtRiskPeriod).isBefore(Instant.now());
  }

}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralCommAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import com.google.inject.assistedinject.Assisted;
import java.time.Duration;
import java.util.LinkedList;
import static java.util.Objects.requireNonNull;
import java.util.Queue;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.BasicPeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralProcessModelEvent;
import static org.opentcs.util.Assertions.checkState;
import org.opentcs.util.ExplainedBoolean;
import org.opentcs.util.event.EventHandler;

/**
 * A {@link PeripheralCommAdapter} implementation that is doing nothing.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralCommAdapter
    extends BasicPeripheralCommAdapter {

  /**
   * The time it takes for loopback peripherals to process a job.
   */
  private static final Duration JOB_PROCESSING_DURATION = Duration.ofSeconds(5);
  /**
   * The kernel's executor.
   */
  private final ScheduledExecutorService kernelExecutor;
  /**
   * The queue of tasks to be executed to simulate the processing of jobs.
   * This queue may contain at most one item at any time.
   */
  private final Queue<Runnable> jobTaskQueue = new LinkedList<>();
  /**
   * A future for the current job task's execution.
   * Indicates whehter the current job task has been executed or whether it is still to be executed.
   */
  private Future<?> currentJobFuture;
  /**
   * Whether the execution of jobs should fail.
   */
  private boolean failJobs;

  /**
   * Creates a new instance.
   *
   * @param location The reference to the location this adapter is attached to.
   * @param eventHandler The handler used to send events to.
   * @param kernelExecutor The kernel's executor.
   */
  @Inject
  public LoopbackPeripheralCommAdapter(@Assisted TCSResourceReference<Location> location,
                                       @ApplicationEventBus EventHandler eventHandler,
                                       @KernelExecutor ScheduledExecutorService kernelExecutor) {
    super(new LoopbackPeripheralProcessModel(location), eventHandler);
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    super.initialize();

    setProcessModel(getProcessModel().withState(PeripheralInformation.State.IDLE));
    sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
  }

  @Override
  public LoopbackPeripheralProcessModel getProcessModel() {
    return (LoopbackPeripheralProcessModel) super.getProcessModel();
  }

  @Override
  public ExplainedBoolean canProcess(PeripheralJob job) {
    if (!isEnabled()) {
      return new ExplainedBoolean(false, "Comm adapter not enabled.");
    }
    else if (hasJobWaitingToBeProcessed()) {
      return new ExplainedBoolean(false, "Busy processing another job.");
    }

    return new ExplainedBoolean(true, "");
  }

  @Override
  public void process(PeripheralJob job, PeripheralJobCallback callback) {
    ExplainedBoolean canProcess = canProcess(job);
    checkState(canProcess.getValue(),
               "%s: Can't process job: %s",
               getProcessModel().getLocation().getName(),
               canProcess.getReason());

    jobTaskQueue.add(() -> {
      if (failJobs) {
        callback.peripheralJobFailed(job);
      }
      else {
        callback.peripheralJobFinished(job);
      }
      setProcessModel(getProcessModel().withState(PeripheralInformation.State.IDLE));
      sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
    });

    setProcessModel(getProcessModel().withState(PeripheralInformation.State.EXECUTING));
    sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);

    if (!getProcessModel().isManualModeEnabled()) {
      currentJobFuture = kernelExecutor.schedule(jobTaskQueue.poll(),
                                                 JOB_PROCESSING_DURATION.getSeconds(),
                                                 TimeUnit.SECONDS);
    }
  }

  @Override
  public void execute(PeripheralAdapterCommand command) {
    command.execute(this);
  }

  @Override
  protected void connectPeripheral() {
  }

  @Override
  protected void disconnectPeripheral() {
  }

  public void enableManualMode(boolean enabled) {
    kernelExecutor.submit(() -> {
      LoopbackPeripheralProcessModel oldProcessModel = getProcessModel();
      setProcessModel(getProcessModel().withManualModeEnabled(enabled));

      if (oldProcessModel.isManualModeEnabled() && !getProcessModel().isManualModeEnabled()) {
        // Job processing mode changed to "automatic". If there's a task that has not yet been 
        // processed while the processing mode was set to "manual", make sure the task is executed 
        // and schedule it for execution on the kernel executor.
        if (!jobTaskQueue.isEmpty()) {
          currentJobFuture = kernelExecutor.submit(jobTaskQueue.poll());
        }
      }

      sendProcessModelChangedEvent(LoopbackPeripheralProcessModel.Attribute.MANUAL_MODE_ENABLED);
    });
  }

  public void pausePeripheral(boolean paused) {
    kernelExecutor.submit(() -> {
      setProcessModel(getProcessModel().withPeripheralPaused(paused));

      // TODO Implement pause

      sendProcessModelChangedEvent(LoopbackPeripheralProcessModel.Attribute.PERIPHERAL_PAUSED);
    });
  }

  public void updateState(PeripheralInformation.State state) {
    kernelExecutor.submit(() -> {
      setProcessModel(getProcessModel().withState(state));
      sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
    });
  }

  public void triggerJobProcessing(boolean failJob) {
    if (!getProcessModel().isManualModeEnabled()) {
      return;
    }

    if (jobTaskQueue.isEmpty() || !isCurrentJobFutureDone()) {
      // There's no job to be processed or we are not yet done processing the current one.
      return;
    }

    currentJobFuture = kernelExecutor.submit(() -> {
      failJobs = failJob;
      jobTaskQueue.poll().run();
      failJobs = false;
    });
  }

  private boolean hasJobWaitingToBeProcessed() {
    return !jobTaskQueue.isEmpty() || !isCurrentJobFutureDone();
  }

  private boolean isCurrentJobFutureDone() {
    if (currentJobFuture == null) {
      return true;
    }

    return currentJobFuture.isDone();
  }

  private void sendProcessModelChangedEvent(
      LoopbackPeripheralProcessModel.Attribute attributeChanged) {
    getEventHandler().onEvent(new PeripheralProcessModelEvent(getProcessModel().getLocation(),
                                                              attributeChanged.name(),
                                                              getProcessModel()));
  }
}


<|start_filename|>openTCS-Common/src/test/java/org/opentcs/util/NumberParsersTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.util.stream.LongStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NumberParsersTest {

  @ParameterizedTest
  @MethodSource("paramsFactory")
  public void parsesNumbers(long number) {
    assertEquals(number, NumberParsers.parsePureDecimalLong(Long.toString(number)));
  }

  public static LongStream paramsFactory() {
    return LongStream.concat(
        LongStream.of(Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MAX_VALUE - 1, Long.MAX_VALUE),
        LongStream.rangeClosed(-100, 100)
    );
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/adminwebapi/AdminWebApiConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.adminwebapi;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Configuration entries for the administration web API.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(AdminWebApiConfiguration.PREFIX)
public interface AdminWebApiConfiguration {

  String PREFIX = "adminwebapi";

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to enable the admin interface.",
      orderKey = "0")
  boolean enable();

  @ConfigurationEntry(
      type = "IP address",
      description = "Address to which to bind the HTTP server, e.g. 0.0.0.0. (Default: 127.0.0.1.)",
      orderKey = "1")
  String bindAddress();

  @ConfigurationEntry(
      type = "Integer",
      description = "Port to which to bind the HTTP server.",
      orderKey = "2")
  int bindPort();

}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/v1/status/binding/StatusMessage.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.servicewebapi.v1.status.binding;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.time.Instant;

/**
 * A generic status message.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
  @JsonSubTypes.Type(value = OrderStatusMessage.class, name = "TransportOrder")
  ,
  @JsonSubTypes.Type(value = VehicleStatusMessage.class, name = "Vehicle")
})
public abstract class StatusMessage {

  @JsonProperty(required = true)
  @JsonPropertyDescription("The (unique) sequence number of this status message")
  private long sequenceNumber;

  @JsonProperty(required = true)
  @JsonPropertyDescription("When this status message was created")
  private Instant creationTimeStamp = Instant.now();

  /**
   * Creates a new instance.
   */
  public StatusMessage() {
  }

  public long getSequenceNumber() {
    return sequenceNumber;
  }

  public void setSequenceNumber(long sequenceNumber) {
    this.sequenceNumber = sequenceNumber;
  }

  public Instant getCreationTimeStamp() {
    return creationTimeStamp;
  }

  public void setCreationTimeStamp(Instant creationTimeStamp) {
    this.creationTimeStamp = creationTimeStamp;
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/persistence/ModelFilePersistor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence;

import java.io.File;
import java.io.IOException;
import javax.annotation.Nonnull;
import javax.swing.filechooser.FileFilter;
import org.opentcs.access.to.model.PlantModelCreationTO;

/**
 * Interface to persist a {@link PlantModelCreationTO} to a local file.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ModelFilePersistor {

  /**
   * Persist the model to the given file.
   *
   * @param model The model to be serialized.
   * @param file The file to serialize into.
   * @return {@code true} if, and only if, the model was successfully serialized
   * @throws java.io.IOException If an exception occurs
   */
  public boolean serialize(PlantModelCreationTO model, File file)
      throws IOException;

  /**
   * Returns the filter that declares which files are supported with this persistor.
   *
   * @return The filter that declares which files are supported with this persistor
   */
  @Nonnull
  public FileFilter getDialogFileFilter();
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayerGroupEditorModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Provides methods to edit layer groups.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerGroupEditorModeling
    extends LayerGroupEditor {

  /**
   * Creates a new layer group.
   */
  void createLayerGroup();

  /**
   * Deletes the layer group with the given layer group ID.
   *
   * @param groupId The ID of the layer group to delete.
   * @throws IllegalArgumentException If a layer group with the given layer group ID doesn't exist.
   */
  void deleteLayerGroup(int groupId)
      throws IllegalArgumentException;
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/adapter/ProcessAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import java.io.Serializable;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObject;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;

/**
 * Receives messages from a <code>ModelComponent</code> and its kernel
 * equivalent and delegates them to the respective other one.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public interface ProcessAdapter
    extends Serializable {

  /**
   * Reads the current properties from the kernel and adopts these for the model object.
   *
   * @param objectService A reference to the object service, in case the adapter needs to access
   * data that is not contained in the given kernel object.
   * @param modelComponent The model component to adopt the properties for.
   * @param systemModel A reference to the system model, in case the adapter needs to access
   * other model components as well.
   * @param tcsObject The kernel's object.
   */
  void updateModelProperties(TCSObject<?> tcsObject,
                             ModelComponent modelComponent,
                             SystemModel systemModel,
                             TCSObjectService objectService);

  /**
   * Reads the current properties from the model component and adopts these for the kernel object.
   *
   * @param modelComponent The model component to read properties from.
   * @param systemModel A reference to the system model, in case the adapter needs to access
   * other model components as well.
   * @param plantModel A transfer object describing the current plant model data.
   * @return A new transfer object, describing the plant model data with the model component's data
   * merged.
   */
  PlantModelCreationTO storeToPlantModel(ModelComponent modelComponent,
                                         SystemModel systemModel,
                                         PlantModelCreationTO plantModel);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/order/package-info.java<|end_filename|>
/**
 * Classes describing transport orders to be processed by vehicles.
 */
package org.opentcs.data.order;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/TransportOrderService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;

/**
 * Provides methods concerning {@link TransportOrder}s and {@link OrderSequence}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface TransportOrderService
    extends TCSObjectService {

  /**
   * Creates a new order sequence.
   * A new order sequence is created with a generated unique ID and all other attributes taken from
   * the given transfer object.
   * A copy of the newly created order sequence is then returned.
   *
   * @param to Describes the order sequence to be created.
   * @return A copy of the newly created order sequence.
   * @throws ObjectUnknownException If any referenced object does not exist.
   * @throws ObjectExistsException If an object with the same name already exists in the model.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  OrderSequence createOrderSequence(OrderSequenceCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException;

  /**
   * Creates a new transport order.
   * A new transport order is created with a generated unique ID and all other attributes taken from
   * the given transfer object.
   * This method also implicitly adds the transport order to its wrapping sequence, if any.
   * A copy of the newly created transport order is then returned.
   *
   * @param to Describes the transport order to be created.
   * @return A copy of the newly created transport order.
   * @throws ObjectUnknownException If any referenced object does not exist.
   * @throws ObjectExistsException If an object with the same name already exists in the model.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  TransportOrder createTransportOrder(TransportOrderCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException;

  /**
   * Marks an order sequence as complete by setting its complete flag.
   *
   * @param ref A reference to the order sequence to be modified.
   * @throws ObjectUnknownException If the referenced order sequence does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void markOrderSequenceComplete(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException, KernelRuntimeException;
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/LocationType.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.model.visualization.LocationRepresentation;

/**
 * Describes the type of a {@link Location}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LocationType
    extends TCSObject<LocationType>
    implements Serializable {

  /**
   * The operations allowed at locations of this type.
   */
  private final List<String> allowedOperations;
  /**
   * The peripheral operations allowed at locations of this type.
   */
  private final List<String> allowedPeripheralOperations;
  /**
   * The information regarding the grahical representation of this location type.
   */
  private final Layout layout;

  /**
   * Creates a new LocationType.
   *
   * @param name The new location type's name.
   */
  public LocationType(String name) {
    super(name);
    this.allowedOperations = new ArrayList<>();
    this.allowedPeripheralOperations = new ArrayList<>();
    this.layout = new Layout();
  }

  private LocationType(String name,
                       Map<String, String> properties,
                       ObjectHistory history,
                       List<String> allowedOperations,
                       List<String> allowedPeripheralOperations,
                       Layout layout) {
    super(name, properties, history);
    this.allowedOperations = listWithoutNullValues(requireNonNull(allowedOperations,
                                                                  "allowedOperations"));
    this.allowedPeripheralOperations
        = listWithoutNullValues(requireNonNull(allowedPeripheralOperations,
                                               "allowedPeripheralOperations"));
    this.layout = requireNonNull(layout, "layout");
  }

  @Override
  public LocationType withProperty(String key, String value) {
    return new LocationType(getName(),
                            propertiesWith(key, value),
                            getHistory(),
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  @Override
  public LocationType withProperties(Map<String, String> properties) {
    return new LocationType(getName(),
                            properties,
                            getHistory(),
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  @Override
  public TCSObject<LocationType> withHistoryEntry(ObjectHistory.Entry entry) {
    return new LocationType(getName(),
                            getProperties(),
                            getHistory().withEntryAppended(entry),
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  @Override
  public TCSObject<LocationType> withHistory(ObjectHistory history) {
    return new LocationType(getName(),
                            getProperties(),
                            history,
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  /**
   * Returns a set of operations allowed with locations of this type.
   *
   * @return A set of operations allowed with locations of this type.
   */
  public List<String> getAllowedOperations() {
    return Collections.unmodifiableList(allowedOperations);
  }

  /**
   * Checks if a given operation is allowed with locations of this type.
   *
   * @param operation The operation to be checked for.
   * @return <code>true</code> if, and only if, the given operation is allowed
   * with locations of this type.
   */
  public boolean isAllowedOperation(String operation) {
    requireNonNull(operation, "operation");
    return allowedOperations.contains(operation);
  }

  /**
   * Creates a copy of this object, with the given allowed operations.
   *
   * @param allowedOperations The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LocationType withAllowedOperations(List<String> allowedOperations) {
    return new LocationType(getName(),
                            getProperties(),
                            getHistory(),
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  /**
   * Returns a set of peripheral operations allowed with locations of this type.
   *
   * @return A set of peripheral operations allowed with locations of this type.
   */
  public List<String> getAllowedPeripheralOperations() {
    return Collections.unmodifiableList(allowedPeripheralOperations);
  }

  /**
   * Creates a copy of this object, with the given allowed peripheral operations.
   *
   * @param allowedPeripheralOperations The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LocationType withAllowedPeripheralOperations(List<String> allowedPeripheralOperations) {
    return new LocationType(getName(),
                            getProperties(),
                            getHistory(),
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  /**
   * Returns the information regarding the grahical representation of this location type.
   *
   * @return The information regarding the grahical representation of this location type.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LocationType withLayout(Layout layout) {
    return new LocationType(getName(),
                            getProperties(),
                            getHistory(),
                            allowedOperations,
                            allowedPeripheralOperations,
                            layout);
  }

  /**
   * Contains information regarding the grahical representation of a location type.
   */
  public static class Layout
      implements Serializable {

    /**
     * The location representation to use for locations with this location type.
     */
    private final LocationRepresentation locationRepresentation;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(LocationRepresentation.NONE);
    }

    /**
     * Creates a new instance.
     *
     * @param locationRepresentation The location representation to use for locations with this
     * location type.
     */
    public Layout(LocationRepresentation locationRepresentation) {
      this.locationRepresentation = requireNonNull(locationRepresentation,
                                                   "locationRepresentation");
    }

    /**
     * Returns the location representation to use for locations with this location type.
     *
     * @return The location representation to use for locations with this location type.
     */
    public LocationRepresentation getLocationRepresentation() {
      return locationRepresentation;
    }

    /**
     * Creates a copy of this object, with the given location representation.
     *
     * @param locationRepresentation The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLocationRepresentation(LocationRepresentation locationRepresentation) {
      return new Layout(locationRepresentation);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/order/OrderConstants.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.order;

/**
 * Defines some constants for {@link TransportOrder}s and {@link OrderSequence}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OrderConstants {

  /**
   * The string representing the <em>any</em> type.
   * Primarily intended to be used for a vehicle to indicate there are no restrictions to its 
   * allowed oder types.
   */
  String TYPE_ANY = "*";
  /**
   * The default type of orders.
   */
  String TYPE_NONE = "-";
  /**
   * A type for charge orders.
   */
  String TYPE_CHARGE = "Charge";
  /**
   * A type for park orders.
   */
  String TYPE_PARK = "Park";
  /**
   * A type for transport orders.
   */
  String TYPE_TRANSPORT = "Transport";
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerGroupCellRenderer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import javax.swing.table.DefaultTableCellRenderer;
import org.opentcs.data.model.visualization.LayerGroup;

/**
 * A table cell renderer for {@link LayerGroup}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class LayerGroupCellRenderer
    extends DefaultTableCellRenderer {

  @Override
  protected void setValue(Object value) {
    setText(((LayerGroup) value).getName());
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/PeripheralDispatcherPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import org.opentcs.components.Lifecycle;

/**
 * Describes a reusable dispatching (sub-)task with a life cycle.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralDispatcherPhase
    extends Runnable,
            Lifecycle {
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/ModelConstants.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

/**
 * Defines some constants used for plant models.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ModelConstants {

  /**
   * The default name for the visual layout.
   */
  String DEFAULT_VISUAL_LAYOUT_NAME = "VLayout";
  /**
   * The name of the default layer.
   */
  String DEFAULT_LAYER_NAME = "Default layer";
  /**
   * The ID of the default layer.
   */
  int DEFAULT_LAYER_ID = 0;
  /**
   * The ordinal of the default layer.
   */
  int DEFAULT_LAYER_ORDINAL = 0;
  /**
   * The name of the default layer group.
   */
  String DEFAULT_LAYER_GROUP_NAME = "Default layer group";
  /**
   * The ID of the default layer group.
   */
  int DEFAULT_LAYER_GROUP_ID = 0;
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/DefaultPortalManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javax.swing.JOptionPane;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.util.I18nCommon;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.gui.dialog.ConnectToServerDialog;
import org.opentcs.util.gui.dialog.ConnectionParamSet;
import org.opentcs.util.gui.dialog.NullConnectionParamSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The default implementation of {@link PortalManager}, providing a single
 * {@link KernelServicePortal}.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPortalManager
    implements PortalManager {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultPortalManager.class);
  /**
   * This class's resource bundle.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nCommon.BUNDLE_PATH);
  /**
   * The handler to send events to.
   */
  private final EventHandler eventHandler;
  /**
   * The connection bookmarks to use.
   */
  private final List<ConnectionParamSet> connectionBookmarks;
  /**
   * The service portal instance we are working with.
   */
  private final KernelServicePortal servicePortal;
  /**
   * The last successfully established connection.
   */
  private ConnectionParamSet lastConnection = new NullConnectionParamSet();
  /**
   * The current connection. {@link NullConnectionParamSet}, if no connection is currently
   * established.
   */
  private ConnectionParamSet currentConnection = new NullConnectionParamSet();

  /**
   * Creates a new instance.
   *
   * @param servicePortal The service portal instance we a working with.
   * @param eventHandler The handler to send events to.
   * @param connectionBookmarks The connection bookmarks to use.
   */
  @Inject
  public DefaultPortalManager(KernelServicePortal servicePortal,
                              @ApplicationEventBus EventHandler eventHandler,
                              List<ConnectionParamSet> connectionBookmarks) {
    this.eventHandler = requireNonNull(eventHandler, "eventHandler");
    this.servicePortal = requireNonNull(servicePortal, "servicePortal");
    this.connectionBookmarks = requireNonNull(connectionBookmarks, "connectionBookmarks");
  }

  @Override
  public boolean connect(ConnectionMode mode) {
    if (isConnected()) {
      return true;
    }

    switch (mode) {
      case AUTO:
        if (connectionBookmarks.isEmpty()) {
          LOG.info("Cannot connect automatically. No connection bookmarks available.");
          return false;
        }
        ConnectionParamSet paramSet = connectionBookmarks.get(0);
        return connect(paramSet.getDescription(), paramSet.getHost(), paramSet.getPort());
      case MANUAL:
        return connectWithDialog();
      case RECONNECT:
        if (lastConnection instanceof NullConnectionParamSet) {
          LOG.info("Cannot reconnect. No portal we were previously connected to.");
          return false;
        }
        return connect(lastConnection.getDescription(),
                       lastConnection.getHost(),
                       lastConnection.getPort());
      default:
        LOG.warn("Unhandled connection mode '{}'. Not connecting.", mode.name());
        return false;
    }
  }

  @Override
  public void disconnect() {
    if (!isConnected()) {
      return;
    }

    eventHandler.onEvent(ConnectionState.DISCONNECTING);

    try {
      servicePortal.logout();
    }
    catch (KernelRuntimeException e) {
      LOG.warn("Exception trying to disconnect from remote portal", e);
    }

    lastConnection = currentConnection;
    currentConnection = new NullConnectionParamSet();
    eventHandler.onEvent(ConnectionState.DISCONNECTED);
  }

  @Override
  public boolean isConnected() {
    return !(currentConnection instanceof NullConnectionParamSet);
  }

  @Override
  public KernelServicePortal getPortal() {
    return servicePortal;
  }

  @Override
  public String getDescription() {
    return currentConnection.getDescription();
  }

  @Override
  public String getHost() {
    return currentConnection.getHost();
  }

  @Override
  public int getPort() {
    return currentConnection.getPort();
  }

  /**
   * Tries to establish a connection to the portal.
   *
   * @param host The name of the host running the kernel/portal.
   * @param port The port to connect to.
   * @return {@code true} if, and only if, the connection was established successfully.
   */
  private boolean connect(String description, String host, int port) {
    try {
      eventHandler.onEvent(ConnectionState.CONNECTING);
      servicePortal.login(host, port);
    }
    catch (KernelRuntimeException e) {
      LOG.warn("Failed to connect to remote portal", e);
      eventHandler.onEvent(ConnectionState.DISCONNECTED);
      JOptionPane.showMessageDialog(null,
                                    BUNDLE.getString("connectToServerDialog.optionPane_noConnection.message"),
                                    BUNDLE.getString("connectToServerDialog.optionPane_noConnection.message"),
                                    JOptionPane.ERROR_MESSAGE);

      // Retry connection attempt
      return connectWithDialog();
    }

    currentConnection = new ConnectionParamSet(description, host, port);
    eventHandler.onEvent(ConnectionState.CONNECTED);
    return true;
  }

  private boolean connectWithDialog() {
    ConnectToServerDialog dialog = new ConnectToServerDialog(connectionBookmarks);
    dialog.setVisible(true);
    if (dialog.getReturnStatus() == ConnectToServerDialog.RET_OK) {
      return connect(dialog.getDescription(), dialog.getHost(), dialog.getPort());
    }

    return false;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/package-info.java<|end_filename|>
/**
 * Interfaces and classes for accessing the kernel from outside, for instance
 * from a remote client or a communication adapter.
 */
package org.opentcs.access;


<|start_filename|>openTCS-PlantOverview-Themes-Default/src/main/java/org/opentcs/guing/plugins/themes/DefaultLocationTheme.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.themes;

import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import java.util.EnumMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.imageio.ImageIO;
import org.opentcs.components.plantoverview.LocationTheme;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.visualization.LocationRepresentation;

/**
 * Default location theme implementation.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultLocationTheme
    implements LocationTheme {

  /**
   * The path containing the images.
   */
  private static final String PATH = "/org/opentcs/guing/plugins/themes/symbols/location/";
  /**
   * The available symbols.
   */
  private static final String[] LOCTYPE_REPRESENTATION_SYMBOLS = {
    "TransferStation.20x20.png", // 0
    "WorkingStation.20x20.png", // 1
    "ChargingStation.20x20.png", // 2
    "None.20x20.png", // 3
  };
  /**
   * A map of property values to image file names.
   */
  private final Map<LocationRepresentation, Image> symbolMap
      = new EnumMap<>(LocationRepresentation.class);

  /**
   * Creates a new instance.
   */
  public DefaultLocationTheme() {
    initSymbolMap();
  }

  @Override
  @Nonnull
  public Image getImageFor(@Nonnull LocationRepresentation representation) {
    requireNonNull(representation, "representation");

    return symbolMap.get(representation);
  }

  @Override
  @Nonnull
  public Image getImageFor(@Nonnull Location location, @Nonnull LocationType locationType) {
    requireNonNull(location, "location");
    requireNonNull(locationType, "locationType");

    LocationRepresentation representation = location.getLayout().getLocationRepresentation();
    if (representation == null || representation == LocationRepresentation.DEFAULT) {
      representation = locationType.getLayout().getLocationRepresentation();
    }
    return getImageFor(representation);
  }

  private void initSymbolMap() {
    // NONE: A location without further description
    symbolMap.put(LocationRepresentation.NONE,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[3]));

    // LOAD_TRANSFER_GENERIC: A generic location for vehicle load transfers.
    symbolMap.put(LocationRepresentation.LOAD_TRANSFER_GENERIC,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[0]));
    // LOAD_TRANSFER_ALT_1: A location for vehicle load transfers, variant 1.
    symbolMap.put(LocationRepresentation.LOAD_TRANSFER_ALT_1,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[0]));
    // LOAD_TRANSFER_ALT_2: A location for vehicle load transfers, variant 2.
    symbolMap.put(LocationRepresentation.LOAD_TRANSFER_ALT_2,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[0]));
    // LOAD_TRANSFER_ALT_3: A location for vehicle load transfers, variant 3.
    symbolMap.put(LocationRepresentation.LOAD_TRANSFER_ALT_3,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[0]));
    // LOAD_TRANSFER_ALT_4: A location for vehicle load transfers, variant 4.
    symbolMap.put(LocationRepresentation.LOAD_TRANSFER_ALT_4,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[0]));
    // LOAD_TRANSFER_ALT_5: A location for vehicle load transfers, variant 5.
    symbolMap.put(LocationRepresentation.LOAD_TRANSFER_ALT_5,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[0]));

    // WORKING_GENERIC: A location for some generic processing, generic variant.
    symbolMap.put(LocationRepresentation.WORKING_GENERIC,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[1]));
    // WORKING_ALT_1: A location for some generic processing, variant 1.
    symbolMap.put(LocationRepresentation.WORKING_ALT_1,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[1]));
    // WORKING_ALT_2: A location for some generic processing, variant 2.
    symbolMap.put(LocationRepresentation.WORKING_ALT_2,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[1]));

    // RECHARGE_GENERIC: A location for recharging a vehicle, generic variant.
    symbolMap.put(LocationRepresentation.RECHARGE_GENERIC,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[2]));
    // RECHARGE_ALT_1: A location for recharging a vehicle, variant 1.
    symbolMap.put(LocationRepresentation.RECHARGE_ALT_1,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[2]));
    // RECHARGE_ALT_2: A location for recharging a vehicle, variant 2.
    symbolMap.put(LocationRepresentation.RECHARGE_ALT_2,
                  loadImageFromPath(LOCTYPE_REPRESENTATION_SYMBOLS[2]));
  }

  private Image loadImageFromPath(String fileName) {
    return loadImage(PATH + fileName);
  }

  private Image loadImage(String fileName) {
    requireNonNull(fileName, "fileName");

    URL url = getClass().getResource(fileName);
    if (url == null) {
      throw new IllegalArgumentException("Invalid image file name " + fileName);
    }
    try {
      return ImageIO.read(url);
    }
    catch (IOException exc) {
      throw new IllegalArgumentException("Exception loading image", exc);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/LocationRepresentation.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model.visualization;

/**
 * Common location representations.
 *
 * @see org.opentcs.data.ObjectPropConstants#LOCTYPE_DEFAULT_REPRESENTATION
 * @see org.opentcs.data.ObjectPropConstants#LOC_DEFAULT_REPRESENTATION
 * @author <NAME> (Fraunhofer IML)
 */
public enum LocationRepresentation {

  /**
   * A (empty) location without any representation.
   */
  NONE,
  /**
   * The default representation inherited from the assigned location type.
   */
  DEFAULT,
  /**
   * A location for vehicle load transfer, generic variant.
   */
  LOAD_TRANSFER_GENERIC,
  /**
   * A location for vehicle load transfers, alternative variant 1.
   */
  LOAD_TRANSFER_ALT_1,
  /**
   * A location for vehicle load transfers, alternative variant 2.
   */
  LOAD_TRANSFER_ALT_2,
  /**
   * A location for vehicle load transfers, alternative variant 3.
   */
  LOAD_TRANSFER_ALT_3,
  /**
   * A location for vehicle load transfers, alternative variant 4.
   */
  LOAD_TRANSFER_ALT_4,
  /**
   * A location for vehicle load transfers, alternative variant 5.
   */
  LOAD_TRANSFER_ALT_5,
  /**
   * A location for some generic processing, generic variant.
   */
  WORKING_GENERIC,
  /**
   * A location for some generic processing, alternative variant 1.
   */
  WORKING_ALT_1,
  /**
   * A location for some generic processing, alternative variant 2.
   */
  WORKING_ALT_2,
  /**
   * A location for recharging a vehicle, generic variant.
   */
  RECHARGE_GENERIC,
  /**
   * A location for recharging a vehicle, alternative variant 1.
   */
  RECHARGE_ALT_1,
  /**
   * A location for recharging a vehicle, alternative variant 2.
   */
  RECHARGE_ALT_2
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/routing/GroupMapper.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.routing;

import java.util.function.Function;
import org.opentcs.data.model.Vehicle;

/**
 * Determines the routing group for a {@link Vehicle} instance.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface GroupMapper
    extends Function<Vehicle, String> {
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/ObjectUnknownException.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data;

import org.opentcs.access.KernelRuntimeException;

/**
 * Thrown when an object was supposed to be returned/removed/modified, but could
 * not be found.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ObjectUnknownException
    extends KernelRuntimeException {

  /**
   * Creates a new ObjectExistsException with the given detail message.
   *
   * @param message The detail message.
   */
  public ObjectUnknownException(String message) {
    super(message);
  }

  /**
   * Creates a new ObjectExistsException for the given object reference.
   *
   * @param ref The object reference.
   */
  public ObjectUnknownException(TCSObjectReference<?> ref) {
    super("Object unknown: " + (ref == null ? "<null>" : ref.toString()));
  }

  /**
   * Creates a new ObjectExistsException with the given detail message and
   * cause.
   *
   * @param message The detail message.
   * @param cause The cause.
   */
  public ObjectUnknownException(String message, Throwable cause) {
    super(message, cause);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/VehicleProcessModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Queue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.notification.UserNotification;

/**
 * An observable model of a vehicle's and its comm adapter's attributes.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleProcessModel {

  /**
   * The maximum number of notifications we want to keep.
   */
  private static final int MAX_NOTIFICATION_COUNT = 100;
  /**
   * A copy of the kernel's Vehicle instance.
   */
  private final Vehicle vehicle;
  /**
   * A reference to the vehicle.
   */
  private final TCSObjectReference<Vehicle> vehicleReference;
  /**
   * Used for implementing property change events.
   */
  private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  /**
   * Whether the comm adapter is currently enabled.
   */
  private boolean commAdapterEnabled;
  /**
   * Whether the comm adapter is currently connected to the vehicle.
   */
  private boolean commAdapterConnected;
  /**
   * The name of the vehicle's current position.
   */
  private String vehiclePosition;
  /**
   * User notifications published by the comm adapter.
   */
  private final Queue<UserNotification> notifications = new LinkedList<>();
  /**
   * The vehicle's precise position.
   */
  private Triple precisePosition;
  /**
   * The vehicle's orientation angle.
   */
  private double orientationAngle = Double.NaN;
  /**
   * The vehicle's energy level.
   */
  private int energyLevel = 100;
  /**
   * The vehicle's load handling devices (state).
   */
  private List<LoadHandlingDevice> loadHandlingDevices = new LinkedList<>();
  /**
   * The vehicle's current state.
   */
  private Vehicle.State state = Vehicle.State.UNKNOWN;

  /**
   * Creates a new instance.
   *
   * @param attachedVehicle The vehicle attached to the new instance.
   */
  public VehicleProcessModel(@Nonnull Vehicle attachedVehicle) {
    this.vehicle = requireNonNull(attachedVehicle, "attachedVehicle");
    this.vehicleReference = vehicle.getReference();
  }

  /**
   * Registers a new property change listener with this model.
   *
   * @param listener The listener to be registered.
   */
  public void addPropertyChangeListener(PropertyChangeListener listener) {
    pcs.addPropertyChangeListener(listener);
  }

  /**
   * Unregisters a property change listener from this model.
   *
   * @param listener The listener to be unregistered.
   */
  public void removePropertyChangeListener(PropertyChangeListener listener) {
    pcs.removePropertyChangeListener(listener);
  }

  /**
   * Returns a reference to the vehicle.
   *
   * @return A reference to the vehicle.
   */
  @Nonnull
  public TCSObjectReference<Vehicle> getVehicleReference() {
    return vehicleReference;
  }

  /**
   * Returns the vehicle's name.
   *
   * @return The vehicle's name.
   */
  @Nonnull
  public String getName() {
    return vehicleReference.getName();
  }

  /**
   * Returns user notifications published by the comm adapter.
   *
   * @return The notifications.
   */
  @Nonnull
  public Queue<UserNotification> getNotifications() {
    return notifications;
  }

  /**
   * Publishes an user notification.
   *
   * @param notification The notification to be published.
   */
  public void publishUserNotification(@Nonnull UserNotification notification) {
    requireNonNull(notification, "notification");

    notifications.add(notification);
    while (notifications.size() > MAX_NOTIFICATION_COUNT) {
      notifications.remove();
    }

    getPropertyChangeSupport().firePropertyChange(Attribute.USER_NOTIFICATION.name(),
                                                  null,
                                                  notification);
  }

  /**
   * Publishes an event via the kernel's event mechanism.
   *
   * @param event The event to be published.
   */
  public void publishEvent(@Nonnull VehicleCommAdapterEvent event) {
    requireNonNull(event, "event");

    getPropertyChangeSupport().firePropertyChange(Attribute.COMM_ADAPTER_EVENT.name(),
                                                  null,
                                                  event);
  }

  /**
   * Indicates whether the comm adapter is currently enabled or not.
   *
   * @return <code>true</code> if, and only if, the comm adapter is currently enabled.
   */
  public boolean isCommAdapterEnabled() {
    return commAdapterEnabled;
  }

  /**
   * Sets the comm adapter's <em>enabled</em> flag.
   *
   * @param commAdapterEnabled The new value.
   */
  public void setCommAdapterEnabled(boolean commAdapterEnabled) {
    boolean oldValue = this.commAdapterEnabled;
    this.commAdapterEnabled = commAdapterEnabled;

    getPropertyChangeSupport().firePropertyChange(Attribute.COMM_ADAPTER_ENABLED.name(),
                                                  oldValue,
                                                  commAdapterEnabled);
  }

  /**
   * Indicates whether the comm adapter is currently connected or not.
   *
   * @return <code>true</code> if, and only if, the comm adapter is currently connected.
   */
  public boolean isCommAdapterConnected() {
    return commAdapterConnected;
  }

  /**
   * Sets the comm adapter's <em>connected</em> flag.
   *
   * @param commAdapterConnected The new value.
   */
  public void setCommAdapterConnected(boolean commAdapterConnected) {
    boolean oldValue = this.commAdapterConnected;
    this.commAdapterConnected = commAdapterConnected;

    getPropertyChangeSupport().firePropertyChange(Attribute.COMM_ADAPTER_CONNECTED.name(),
                                                  oldValue,
                                                  commAdapterConnected);
  }

  /**
   * Returns the vehicle's current position.
   *
   * @return The position.
   */
  @Nullable
  public String getVehiclePosition() {
    return vehiclePosition;
  }

  /**
   * Updates the vehicle's current position.
   *
   * @param position The new position
   */
  public void setVehiclePosition(@Nullable String position) {
    // Otherwise update the position, notify listeners and let the kernel know.
    String oldValue = this.vehiclePosition;
    vehiclePosition = position;

    getPropertyChangeSupport().firePropertyChange(Attribute.POSITION.name(),
                                                  oldValue,
                                                  position);
  }

  /**
   * Returns the vehicle's precise position.
   *
   * @return The vehicle's precise position.
   */
  @Nullable
  public Triple getVehiclePrecisePosition() {
    return precisePosition;
  }

  /**
   * Sets the vehicle's precise position.
   *
   * @param position The new position.
   */
  public void setVehiclePrecisePosition(@Nullable Triple position) {
    // Otherwise update the position, notify listeners and let the kernel know.
    Triple oldValue = this.precisePosition;
    this.precisePosition = position;

    getPropertyChangeSupport().firePropertyChange(Attribute.PRECISE_POSITION.name(),
                                                  oldValue,
                                                  position);
  }

  /**
   * Returns the vehicle's current orientation angle.
   *
   * @return The vehicle's current orientation angle.
   * @see Vehicle#getOrientationAngle()
   */
  public double getVehicleOrientationAngle() {
    return orientationAngle;
  }

  /**
   * Sets the vehicle's current orientation angle.
   *
   * @param angle The new angle
   */
  public void setVehicleOrientationAngle(double angle) {
    double oldValue = this.orientationAngle;
    this.orientationAngle = angle;

    getPropertyChangeSupport().firePropertyChange(Attribute.ORIENTATION_ANGLE.name(),
                                                  oldValue,
                                                  angle);
  }

  /**
   * Returns the vehicle's current energy level.
   *
   * @return The vehicle's current energy level.
   */
  public int getVehicleEnergyLevel() {
    return energyLevel;
  }

  /**
   * Sets the vehicle's current energy level.
   *
   * @param newLevel The new level.
   */
  public void setVehicleEnergyLevel(int newLevel) {
    int oldValue = this.energyLevel;
    this.energyLevel = newLevel;

    getPropertyChangeSupport().firePropertyChange(Attribute.ENERGY_LEVEL.name(),
                                                  oldValue,
                                                  newLevel);
  }

  /**
   * Returns the vehicle's load handling devices.
   *
   * @return The vehicle's load handling devices.
   */
  @Nonnull
  public List<LoadHandlingDevice> getVehicleLoadHandlingDevices() {
    return loadHandlingDevices;
  }

  /**
   * Sets the vehicle's load handling devices.
   *
   * @param devices The new devices
   */
  public void setVehicleLoadHandlingDevices(@Nonnull List<LoadHandlingDevice> devices) {
    List<LoadHandlingDevice> devs = new LinkedList<>();
    for (LoadHandlingDevice lhd : devices) {
      devs.add(new LoadHandlingDevice(lhd));
    }
    List<LoadHandlingDevice> oldValue = this.loadHandlingDevices;
    this.loadHandlingDevices = devs;

    getPropertyChangeSupport().firePropertyChange(Attribute.LOAD_HANDLING_DEVICES.name(),
                                                  oldValue,
                                                  devs);
  }

  /**
   * Sets a property of the vehicle.
   *
   * @param key The property's key.
   * @param value The property's new value.
   */
  public void setVehicleProperty(@Nonnull String key, @Nullable String value) {
    getPropertyChangeSupport().firePropertyChange(Attribute.VEHICLE_PROPERTY.name(),
                                                  null,
                                                  new VehiclePropertyUpdate(key, value));
  }

  /**
   * Returns the vehicle's current state.
   *
   * @return The state
   */
  @Nonnull
  public Vehicle.State getVehicleState() {
    return state;
  }

  /**
   * Sets the vehicle's current state.
   *
   * @param newState The new state
   */
  public void setVehicleState(@Nonnull Vehicle.State newState) {
    Vehicle.State oldState = this.state;
    this.state = newState;

    getPropertyChangeSupport().firePropertyChange(Attribute.STATE.name(), oldState, newState);

    if (oldState != Vehicle.State.ERROR && newState == Vehicle.State.ERROR) {
      publishUserNotification(new UserNotification(getName(),
                                                   "Vehicle state changed to ERROR",
                                                   UserNotification.Level.NOTEWORTHY));
    }
    else if (oldState == Vehicle.State.ERROR && newState != Vehicle.State.ERROR) {
      publishUserNotification(new UserNotification(getName(),
                                                   "Vehicle state is no longer ERROR",
                                                   UserNotification.Level.NOTEWORTHY));
    }
  }

  /**
   * Sets a property of the transport order the vehicle is currently processing.
   *
   * @param key The property's key.
   * @param value The property's new value.
   */
  public void setTransportOrderProperty(@Nonnull String key, @Nullable String value) {
    // XXX Should check if property already has the new value.
    getPropertyChangeSupport().firePropertyChange(Attribute.TRANSPORT_ORDER_PROPERTY.name(),
                                                  null,
                                                  new TransportOrderPropertyUpdate(key, value));
  }

  /**
   * Notifies observers that the given command has been added to the comm adapter's command queue.
   *
   * @param enqueuedCommand The command that has been added to the queue.
   */
  public void commandEnqueued(@Nonnull MovementCommand enqueuedCommand) {
    getPropertyChangeSupport().firePropertyChange(Attribute.COMMAND_ENQUEUED.name(),
                                                  null,
                                                  enqueuedCommand);
  }

  /**
   * Notifies observers that the given command has been sent to the associated vehicle.
   *
   * @param sentCommand The command that has been sent to the vehicle.
   */
  public void commandSent(@Nonnull MovementCommand sentCommand) {
    getPropertyChangeSupport().firePropertyChange(Attribute.COMMAND_SENT.name(),
                                                  null,
                                                  sentCommand);
  }

  /**
   * Notifies observers that the given command has been executed by the comm adapter/vehicle.
   *
   * @param executedCommand The command that has been executed.
   */
  public void commandExecuted(@Nonnull MovementCommand executedCommand) {
    getPropertyChangeSupport().firePropertyChange(Attribute.COMMAND_EXECUTED.name(),
                                                  null,
                                                  executedCommand);
  }

  /**
   * Notifies observers that the given command could not be executed by the comm adapter/vehicle.
   *
   * @param failedCommand The command that could not be executed.
   */
  public void commandFailed(@Nonnull MovementCommand failedCommand) {
    getPropertyChangeSupport().firePropertyChange(Attribute.COMMAND_FAILED.name(),
                                                  null,
                                                  failedCommand);
  }

  protected PropertyChangeSupport getPropertyChangeSupport() {
    return pcs;
  }

  /**
   * A notification object sent to observers to indicate a change of a property.
   */
  public static class PropertyUpdate {

    /**
     * The property's key.
     */
    private final String key;
    /**
     * The property's new value.
     */
    private final String value;

    /**
     * Creates a new instance.
     *
     * @param key The key.
     * @param value The new value.
     */
    public PropertyUpdate(String key, String value) {
      this.key = requireNonNull(key, "key");
      this.value = value;
    }

    /**
     * Returns the property's key.
     *
     * @return The property's key.
     */
    public String getKey() {
      return key;
    }

    /**
     * Returns the property's new value.
     *
     * @return The property's new value.
     */
    public String getValue() {
      return value;
    }
  }

  /**
   * A notification object sent to observers to indicate a change of a vehicle's property.
   */
  public static class VehiclePropertyUpdate
      extends PropertyUpdate {

    /**
     * Creates a new instance.
     *
     * @param key The property's key.
     * @param value The new value.
     */
    public VehiclePropertyUpdate(String key, String value) {
      super(key, value);
    }
  }

  /**
   * A notification object sent to observers to indicate a change of a transport order's property.
   */
  public static class TransportOrderPropertyUpdate
      extends PropertyUpdate {

    /**
     * Creates a new instance.
     *
     * @param key The property's key.
     * @param value The new value.
     */
    public TransportOrderPropertyUpdate(String key, String value) {
      super(key, value);
    }
  }

  /**
   * Notification arguments to indicate some change.
   */
  public enum Attribute {
    /**
     * Indicates a change of the comm adapter's <em>enabled</em> setting.
     */
    COMM_ADAPTER_ENABLED,
    /**
     * Indicates a change of the comm adapter's <em>connected</em> setting.
     */
    COMM_ADAPTER_CONNECTED,
    /**
     * Indicates a change of the vehicle's position.
     */
    POSITION,
    /**
     * Indicates a change of the vehicle's precise position.
     */
    PRECISE_POSITION,
    /**
     * Indicates a change of the vehicle's orientation angle.
     */
    ORIENTATION_ANGLE,
    /**
     * Indicates a change of the vehicle's energy level.
     */
    ENERGY_LEVEL,
    /**
     * Indicates a change of the vehicle's load handling devices.
     */
    LOAD_HANDLING_DEVICES,
    /**
     * Indicates a change of the vehicle's state.
     */
    STATE,
    /**
     * Indicates a new user notification was published.
     */
    USER_NOTIFICATION,
    /**
     * Indicates a new comm adapter event was published.
     */
    COMM_ADAPTER_EVENT,
    /**
     * Indicates a command was enqueued.
     */
    COMMAND_ENQUEUED,
    /**
     * Indicates a command was sent.
     */
    COMMAND_SENT,
    /**
     * Indicates a command was executed successfully.
     */
    COMMAND_EXECUTED,
    /**
     * Indicates a command failed.
     */
    COMMAND_FAILED,
    /**
     * Indicates a change of a vehicle property.
     */
    VEHICLE_PROPERTY,
    /**
     * Indicates a change of a transport order property.
     */
    TRANSPORT_ORDER_PROPERTY;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/ModelBasedFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import org.jhotdraw.draw.Figure;
import org.opentcs.guing.model.DrawnModelComponent;
import org.opentcs.guing.model.ModelComponent;

/**
 * A figure that is based on/is a graphical representation for a {@link ModelComponent}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ModelBasedFigure
    extends Figure {

  /**
   * Returns the model component for this figure.
   *
   * @return The model component for this figure.
   */
  public DrawnModelComponent getModel();
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/TransportOrderData.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;

/**
 * <code>TransportOrderData</code> implements functionalities for creating
 * and for local storing of xml telegrams.
 * The transport/drive oder data is stored in this class.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderData {

  /**
   * The new transport order's deadline.
   */
  private Deadline deadline = Deadline.PLUS_ONE_HOUR;
  /**
   * The drive orders the transport order consists of.
   */
  private final List<DriveOrderStructure> driveOrders = new ArrayList<>();
  /**
   * A reference to the vehicle intended to process the transport order.
   */
  private TCSObjectReference<Vehicle> intendedVehicle;
  /**
   * Properties of the transport order data.
   */
  private final Map<String, String> properties = new TreeMap<>();

  /**
   * Creates a new instance of TransportOrderData, that performes
   * XML telegram generation. This class implements also functions for
   * management of data structures that contains the data of
   * gui-generated elements and data need for creating a new XML telegram and
   * for creating of a new transport order instances.
   */
  public TransportOrderData() {
  }

  /**
   * Adds a new DriveOrderStructure to this transport order.
   *
   * @param driveOrder The drive order that shall be added
   */
  public void addDriveOrder(DriveOrderStructure driveOrder) {
    Objects.requireNonNull(driveOrder, "driveOrder is null");
    driveOrders.add(driveOrder);
  }

  /**
   * Removes a <code>DriveOrderStructure</code> from the list of drive orders.
   *
   * @param index The index of the drive order in the list.
   */
  public void removeDriveOrder(int index) {
    driveOrders.remove(index);
  }

  /**
   * Returns a list of matched destinations that have to be travelled when
   * processing the new generated transport order.
   *
   * @return The list of destinations that have to be travelled when processing
   * the new generated transport order.
   */
  public List<DriveOrder.Destination> getDestinations() {
    List<DriveOrder.Destination> destinations = new LinkedList<>();
    for (DriveOrderStructure i : driveOrders) {
      destinations.add(new DriveOrder.Destination(i.getDriveOrderLocation())
          .withOperation(i.getDriveOrderVehicleOperation()));
    }
    return destinations;
  }

  /**
   * Returns the properties of this transport order data.
   *
   * @return The properties
   */
  public Map<String, String> getProperties() {
    return properties;
  }

  /**
   * Adds a property.
   *
   * @param key The key
   * @param value The value
   */
  public void addProperty(String key, String value) {
    if (key == null || value == null) {
      return;
    }
    properties.put(key, value);
  }

  /**
   * Returns a list of drive orders.
   *
   * @return The list of drive orders.
   */
  public List<DriveOrderStructure> getDriveOrders() {
    return driveOrders;
  }

  /**
   * Returns a deadline.
   *
   * @return The deadline.
   */
  public Deadline getDeadline() {
    return this.deadline;
  }

  /**
   * Sets the currect deadline for representing transport order.
   *
   * @param newDeadline The new deadline.
   */
  public void setDeadline(Deadline newDeadline) {
    this.deadline = newDeadline;
  }

  /**
   * Returns a reference to the vehicle intended to process the order.
   *
   * @return A reference to the vehicle intended to process the order.
   */
  public TCSObjectReference<Vehicle> getIntendedVehicle() {
    return intendedVehicle;
  }

  /**
   * Sets a reference to the vehicle intended to process the order.
   *
   * @param vehicle A reference to the vehicle intended to process the order.
   */
  public void setIntendedVehicle(TCSObjectReference<Vehicle> vehicle) {
    intendedVehicle = vehicle;
  }

  /**
   * The enumeration of possible default deadline values.
   */
  public enum Deadline {

    /**
     * The deadline value is five minutes in the past.
     */
    MINUS_FIVE_MINUTES("-5 min.", -60 * 5 * 1000),
    /**
     * The deadline value is five minutes in the future.
     */
    PLUS_FIVE_MINUTES("5 min.", 60 * 5 * 1000),
    /**
     * The deadline value is a half hour in the past.
     */
    MINUS_HALF_HOUR("-30 min.", -60 * 30 * 1000),
    /**
     * The deadline value is a half hour in the future.
     */
    PLUS_HALF_HOUR("30 min.", 60 * 30 * 1000),
    /**
     * The deadline value is a one hour in the future.
     */
    PLUS_ONE_HOUR(" 1 h.", 60 * 60 * 1000),
    /**
     * The deadline value is two hours in the future.
     */
    PLUS_TWO_HOURS(" 2 h.", 2 * 60 * 60 * 1000);

    /**
     * The deadline value (in ms).
     */
    private final int millis;
    /**
     * The deadline label.
     */
    private final String label;

    /**
     * Creates a new Deadline.
     *
     * @param newLabel This deadline as a string
     * @param deadline The value
     */
    private Deadline(String newLabel, int deadline) {
      this.millis = deadline;
      this.label = newLabel;
    }

    /**
     * Returns a deadline value (in ms relative to the current time).
     *
     * @return The deadline value (in ms relative to the current time).
     */
    public int getTime() {
      return this.millis;
    }

    /**
     * Returns an absolute time.
     *
     * @return The absolute time.
     */
    public Date getAbsoluteTime() {
      Calendar calendar = Calendar.getInstance();
      calendar.add(Calendar.MILLISECOND, this.getTime());
      return calendar.getTime();
    }

    @Override
    public String toString() {
      return this.label;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/test/java/org/opentcs/guing/components/properties/type/PercentPropertyTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.junit.*;
import static org.junit.Assert.assertEquals;
import org.opentcs.guing.model.AbstractModelComponent;

/**
 * A test for a percent property.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PercentPropertyTest {

  private PercentProperty property;

  @Test
  public void testPropertyRange() {
    property = new PercentProperty(new DummyComponent());
    assertEquals(0, property.getValidRange().getMin(), 0);
    assertEquals(100, property.getValidRange().getMax(), 0);
  }

  private class DummyComponent
      extends AbstractModelComponent {
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/gui/StringListCellRenderer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.gui;

import java.awt.Component;
import static java.util.Objects.requireNonNull;
import java.util.function.Function;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;

/**
 * Renders values to JLabels.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <E> The type of the values to be rendered.
 */
public class StringListCellRenderer<E>
    implements ListCellRenderer<E> {

  /**
   * A default renderer for creating the label.
   */
  private final DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
  /**
   * Returns a String representation of E.
   */
  private final Function<E, String> representer;

  /**
   * Creates an instance.
   *
   * @param representer a string representation provider for the values of the list.
   * Null value as parameter for the representer is possible.
   * The result is set as text of the JLabel.
   */
  public StringListCellRenderer(Function<E, String> representer) {
    this.representer = requireNonNull(representer, "representer");
  }

  @Override
  public Component getListCellRendererComponent(JList<? extends E> list,
                                                E value,
                                                int index,
                                                boolean isSelected,
                                                boolean cellHasFocus) {
    JLabel label = (JLabel) defaultRenderer.getListCellRendererComponent(list,
                                                                         value,
                                                                         index,
                                                                         isSelected,
                                                                         cellHasFocus);
    label.setText(representer.apply(value));
    return label;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/ResourceAllocationException.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import org.opentcs.access.KernelException;

/**
 * Thrown when allocating resources for a {@link Scheduler.Client Scheduler.Client} is impossible.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ResourceAllocationException
    extends KernelException {

  /**
   * Creates a new ResourceAllocationException with the given detail message.
   *
   * @param message The detail message.
   */
  public ResourceAllocationException(String message) {
    super(message);
  }

  /**
   * Creates a new ResourceAllocationException with the given detail message and
   * cause.
   *
   * @param message The detail message.
   * @param cause The cause.
   */
  public ResourceAllocationException(String message, Throwable cause) {
    super(message, cause);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/VehicleCommAdapterEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;

/**
 * An event emitted by a communication adapter.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleCommAdapterEvent
    implements Serializable {

  /**
   * The name of the adapter that emitted this event.
   */
  private final String adapterName;
  /**
   * An optional appendix containing additional arbitrary information about the
   * event.
   */
  private final Serializable appendix;

  /**
   * Creates a new instance.
   *
   * @param adapterName The name of the adapter that emitted this event.
   * @param appendix An optional appendix containing additional arbitrary
   * information about the event.
   */
  public VehicleCommAdapterEvent(String adapterName, Serializable appendix) {
    this.adapterName = requireNonNull(adapterName, "adapterName");
    this.appendix = appendix;
  }

  /**
   * Creates a new instance without an appendix.
   *
   * @param adapterName The name of the adapter that emitted this event.
   */
  public VehicleCommAdapterEvent(String adapterName) {
    this(adapterName, null);
  }

  /**
   * Returns the name of the adapter that emitted this event.
   *
   * @return The name of the adapter that emitted this event.
   */
  public String getAdapterName() {
    return adapterName;
  }

  /**
   * Returns the (optional) appendix containing additional arbitrary information
   * about the event.
   *
   * @return The (optional) appendix containing additional arbitrary information
   * about the event.
   */
  public Serializable getAppendix() {
    return appendix;
  }

  @Override
  public String toString() {
    return "VehicleCommAdapterEvent{"
        + "adapterName=" + adapterName
        + ", appendix=" + appendix
        + '}';
  }

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardPeripheralJobService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.components.kernel.services.InternalPeripheralJobService;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.kernel.workingset.PeripheralJobPool;

/**
 * This class is the standard implementation of the {@link PeripheralJobService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardPeripheralJobService
    extends AbstractTCSObjectService
    implements InternalPeripheralJobService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The peripheral job facade to the object pool.
   */
  private final PeripheralJobPool jobPool;

  /**
   * Creates a new instance.
   *
   * @param objectService The tcs obejct service.
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param jobPool The peripheral job pool to be used.
   */
  @Inject
  public StandardPeripheralJobService(TCSObjectService objectService,
                                      @GlobalSyncObject Object globalSyncObject,
                                      PeripheralJobPool jobPool) {
    super(objectService);
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.jobPool = requireNonNull(jobPool, "jobPool");
  }

  @Override
  public void updatePeripheralJobState(TCSObjectReference<PeripheralJob> ref,
                                       PeripheralJob.State state)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      jobPool.setPeripheralJobState(ref, state);
    }
  }

  @Override
  public PeripheralJob createPeripheralJob(PeripheralJobCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException {
    synchronized (globalSyncObject) {
      return jobPool.createPeripheralJob(to);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/UserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import org.opentcs.guing.model.ModelComponent;

/**
 * A UserObject has the purpose of representing a model component in the TreeView.
 * It manages its model component and is responsible for executing user interactions e.g. selecting,
 * deleting, double clicking.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @see ModelComponent
 */
public interface UserObject {

  /**
   * Returns the wrapped model component.
   *
   * @return the wrapped model component.
   */
  ModelComponent getModelComponent();

  /**
   * Return the popup menu for the model component.
   *
   * @return the popup menu for the model component.
   */
  JPopupMenu getPopupMenu();

  /**
   * Return the icon for this user object.
   *
   * @return the icon for this user object.
   */
  ImageIcon getIcon();

  /**
   * Is called when the object is selected in the tree view.
   */
  void selected();

  /**
   * Is called when this object is removed from the tree view.
   *
   * @return
   */
  boolean removed();

  /**
   * Is called when the object was right clicked in the tree view.
   *
   * @param component
   * @param x X position of the mouse click.
   * @param y Y position of the mouse click.
   */
  void rightClicked(JComponent component, int x, int y);

  /**
   * Is called when the object is double clicked in the tree view.
   */
  void doubleClicked();

  /**
   * Returns the parent component that contains this user object.
   * (Typically a <code>SimpleFolder</code>
   *
   * @return The parent <code>ModelComponent</code>.
   */
  ModelComponent getParent();

  /**
   * Sets the parent component.
   *
   * @param parent The parent.
   */
  void setParent(ModelComponent parent);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/Block.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.awt.Color;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;

/**
 * An aggregation of resources with distinct usage rules depending on the block's type.
 *
 * @see TCSResource
 * @author <NAME> (Fraunhofer IML)
 */
public class Block
    extends TCSResource<Block>
    implements Serializable {

  /**
   * This block's type.
   */
  private final Type type;
  /**
   * The resources aggregated in this block.
   */
  private final Set<TCSResourceReference<?>> members;
  /**
   * The information regarding the grahical representation of this block.
   */
  private final Layout layout;

  /**
   * Creates an empty block.
   *
   * @param name This block's name.
   */
  public Block(String name) {
    super(name);
    this.type = Type.SINGLE_VEHICLE_ONLY;
    this.members = new HashSet<>();
    this.layout = new Layout();
  }

  private Block(String name,
                Map<String, String> properties,
                ObjectHistory history,
                Type type,
                Set<TCSResourceReference<?>> members,
                Layout layout) {
    super(name, properties, history);
    this.type = type;
    this.members = new HashSet<>(requireNonNull(members, "members"));
    this.layout = requireNonNull(layout, "layout");
  }

  @Override
  public Block withProperty(String key, String value) {
    return new Block(getName(),
                     propertiesWith(key, value),
                     getHistory(),
                     type,
                     members,
                     layout);
  }

  @Override
  public Block withProperties(Map<String, String> properties) {
    return new Block(getName(),
                     properties,
                     getHistory(),
                     type,
                     members,
                     layout);
  }

  @Override
  public TCSObject<Block> withHistoryEntry(ObjectHistory.Entry entry) {
    return new Block(getName(),
                     getProperties(),
                     getHistory().withEntryAppended(entry),
                     type,
                     members,
                     layout);
  }

  @Override
  public TCSObject<Block> withHistory(ObjectHistory history) {
    return new Block(getName(),
                     getProperties(),
                     history,
                     type,
                     members,
                     layout);
  }

  /**
   * Retruns the type of this block.
   *
   * @return The type of this block.
   */
  public Type getType() {
    return type;
  }

  /**
   * Creates a copy of this object, with the given type.
   *
   * @param type The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Block withType(Type type) {
    return new Block(getName(),
                     getProperties(),
                     getHistory(),
                     type,
                     members,
                     layout);
  }

  /**
   * Returns an unmodifiable set of all members of this block.
   *
   * @return An unmodifiable set of all members of this block.
   */
  public Set<TCSResourceReference<?>> getMembers() {
    return Collections.unmodifiableSet(members);
  }

  /**
   * Creates a copy of this object, with the given members.
   *
   * @param members The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Block withMembers(Set<TCSResourceReference<?>> members) {
    return new Block(getName(),
                     getProperties(),
                     getHistory(),
                     type,
                     members,
                     layout);
  }

  /**
   * Returns the information regarding the grahical representation of this block.
   *
   * @return The information regarding the grahical representation of this block.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Block withLayout(Layout layout) {
    return new Block(getName(),
                     getProperties(),
                     getHistory(),
                     type,
                     members,
                     layout);
  }

  /**
   * Describes the types of blocks in a driving course.
   */
  public enum Type {

    /**
     * The resources aggregated in this block can only be used by one vehicle at the same time.
     */
    SINGLE_VEHICLE_ONLY,
    /**
     * The resources aggregated in this block can be used by multiple vehicles, but only if they
     * enter the block in the same direction.
     */
    SAME_DIRECTION_ONLY;
  }

  /**
   * Contains information regarding the grahical representation of a block.
   */
  public static class Layout
      implements Serializable {

    /**
     * The color in which block elements are to be emphasized.
     */
    private final Color color;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(Color.RED);
    }

    /**
     * Creates a new instance.
     *
     * @param color The color in which block elements are to be emphasized.
     */
    public Layout(Color color) {
      this.color = requireNonNull(color, "color");
    }

    /**
     * Returns the color in which block elements are to be emphasized.
     *
     * @return The color in which block elements are to be emphasized.
     */
    public Color getColor() {
      return color;
    }

    /**
     * Creates a copy of this object, with the given color.
     *
     * @param color The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withColor(Color color) {
      return new Layout(color);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/AscendingTreeViewNameComparator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree;

import java.util.Comparator;

/**
 * Compares two elements of a tree view for sorting.
 * Sorts based on their name in descending order.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class AscendingTreeViewNameComparator
    implements Comparator<Object> {

  /**
   * Creates a new instance.
   */
  public AscendingTreeViewNameComparator() {
  }

  @Override
  public int compare(Object o1, Object o2) {
    String s1 = o1.toString();
    String s2 = o2.toString();
    s1 = s1.toLowerCase();
    s2 = s2.toLowerCase();

    return s1.compareTo(s2);
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/EditableComboBoxEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.HashSet;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.function.Function;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.plaf.basic.BasicComboBoxEditor;

/**
 * An editor for editable combo boxes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EditableComboBoxEditor<E>
    extends BasicComboBoxEditor
    implements ListDataListener {

  /**
   * Represents the model of the comboBox as a set.
   */
  private final Set<E> content = new HashSet<>();
  /**
   * The relevant combobox.
   */
  private final JComboBox<E> comboBox;
  /**
   * Returns the string representation for the combo box's selected item.
   */
  private final Function<E, String> representer;

  /**
   * Creates and instance and configures an {@link EditableComboBoxListener} for the editor.
   *
   * @param validationListeners validation listeners.
   * @param comboBox the comboBox that is edited.
   * @param representer Returns the string representation for the combo box's selected item.
   */
  public EditableComboBoxEditor(List<ValidationListener> validationListeners,
                                JComboBox<E> comboBox,
                                Function<E, String> representer) {
    this.comboBox = requireNonNull(comboBox, "comboBox");
    this.representer = requireNonNull(representer, "representer");
    editor.getDocument().addDocumentListener(new EditableComboBoxListener<>(content,
                                                                            validationListeners,
                                                                            editor,
                                                                            representer));
  }

  @Override
  public void intervalAdded(ListDataEvent e) {
    loadContent();
  }

  @Override
  public void intervalRemoved(ListDataEvent e) {
    loadContent();
  }

  @Override
  public void contentsChanged(ListDataEvent e) {
    loadContent();
  }

  private void loadContent() {
    //get the current comboBoxModel and add the modelelements to content
    ComboBoxModel<E> model = comboBox.getModel();
    for (int i = 0; i < model.getSize(); i++) {

      content.add(model.getElementAt(i));

    }
  }

  @Override
  public Object getItem() {
    //if the panel tries to capture the input, this method guarantees that 
    for (E p : content) {
      if (representer.apply(p).equals(editor.getText())) {
        return p;
      }
    }
    return null;
  }

  @Override
  @SuppressWarnings("unchecked")
  public void setItem(Object anObject) {
    editor.setText(representer.apply((E) anObject));
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/event/AttributesChangeListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.event;

/**
 * Interface that controllers/views implement.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @see AttributesChangeEvent
 */
public interface AttributesChangeListener {

  /**
   * Event received when the model has been changed.
   *
   * @param e The event.
   */
  void propertiesChanged(AttributesChangeEvent e);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/ModelToLayoutMenuItem.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus;

import com.google.inject.assistedinject.Assisted;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.model.visualization.ElementPropKeys;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.components.drawing.figures.FigureConstants;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.properties.CoordinateUndoActivity;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.NullAttributesChangeListener;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.components.properties.type.ModelAttribute;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.event.ResetInteractionToolCommand;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.event.EventHandler;

/**
 * A menu item for copying the value of the model properties of selected points
 * or locations to the corresponding layout properties.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelToLayoutMenuItem
    extends JMenuItem {

  /**
   * The <code>DrawingEditor</code> instance.
   */
  private final DrawingEditor drawingEditor;
  /**
   * The UndoRedoManager instance to be used.
   */
  private final UndoRedoManager undoRedoManager;
  /**
   * Where we send events.
   */
  private final EventHandler eventBus;
  /**
   * The components factory.
   */
  private final MenuItemComponentsFactory componentsFactory;
  /**
   * A flag if the values of ALL points and location shall be copied when
   * the menu item is clicked. If false only the selected figures will be
   * considered.
   */
  private final boolean copyAll;

  /**
   * Creates a new instance.
   *
   * @param drawingEditor A <code>DrawingEditor</code> instance.
   * @param undoRedoManager The application's undo/redo manager.
   * @param eventHandler Where this instance sends events.
   * @param componentsFactory The components factory.
   * @param copyAll Indicates whether the values of ALL points and locations
   * shall be copied when the menu item is clicked. If false only the selected
   * figures will be considered.
   */
  @Inject
  public ModelToLayoutMenuItem(OpenTCSDrawingEditor drawingEditor,
                               UndoRedoManager undoRedoManager,
                               @ApplicationEventBus EventHandler eventHandler,
                               MenuItemComponentsFactory componentsFactory,
                               @Assisted boolean copyAll) {
    super(ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH)
        .getString("modelToLayoutMenuItem.text"));
    this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
    this.undoRedoManager = requireNonNull(undoRedoManager, "undoRedoManager");
    this.eventBus = requireNonNull(eventHandler, "eventHandler");
    this.componentsFactory = requireNonNull(componentsFactory, "componentsFactory");
    this.copyAll = copyAll;

    setIcon(new ImageIcon(
        getClass().getClassLoader().getResource("org/opentcs/guing/res/symbols/menu/arrow-down-3.png")));
    setMargin(new Insets(0, 2, 0, 2));
    addActionListener();
  }

  private void addActionListener() {
    addActionListener(new ActionListener() {

      @Override
      public void actionPerformed(ActionEvent e) {
        for (Figure figure : copyAll
            ? getView().getDrawing().getFiguresFrontToBack()
            : getView().getSelectedFigures()) {
          ModelComponent model = figure.get(FigureConstants.MODEL);
          if (model instanceof PointModel || model instanceof LocationModel) {
            updateLayoutX(model);
            updateLayoutY(model);
            // ... and move the figure
            final LabeledFigure labeledFigure = (LabeledFigure) figure;
            labeledFigure.propertiesChanged(new AttributesChangeEvent(
                new NullAttributesChangeListener(), model));

            model.propertiesChanged(new NullAttributesChangeListener());
            eventBus.onEvent(new ResetInteractionToolCommand(this));
          }
        }
      }
    });
  }

  private DrawingView getView() {
    return drawingEditor.getActiveView();
  }

  private void updateLayoutY(ModelComponent model) {
    CoordinateProperty modelProperty;
    if (model instanceof PointModel) {
      modelProperty = (CoordinateProperty) model.getProperty(PointModel.MODEL_Y_POSITION);
    }
    else {
      modelProperty = (CoordinateProperty) model.getProperty(LocationModel.MODEL_Y_POSITION);
    }
    CoordinateUndoActivity cua
        = componentsFactory.createModelToLayoutCoordinateUndoActivity(modelProperty);
    cua.snapShotBeforeModification();
    modelProperty.setChangeState(ModelAttribute.ChangeState.DETAIL_CHANGED);
    StringProperty spy;
    if (model instanceof PointModel) {
      spy = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_Y);
    }
    else {
      spy = (StringProperty) model.getProperty(ElementPropKeys.LOC_POS_Y);
    }
    spy.setText(String.valueOf(((Number) modelProperty.getValue()).intValue()));
    spy.markChanged();
    cua.snapShotAfterModification();
    undoRedoManager.addEdit(cua);
  }

  private void updateLayoutX(ModelComponent model) {
    CoordinateProperty modelProperty;
    if (model instanceof PointModel) {
      modelProperty = (CoordinateProperty) model.getProperty(PointModel.MODEL_X_POSITION);
    }
    else {
      modelProperty = (CoordinateProperty) model.getProperty(LocationModel.MODEL_X_POSITION);
    }
    CoordinateUndoActivity cua
        = componentsFactory.createModelToLayoutCoordinateUndoActivity(modelProperty);
    cua.snapShotBeforeModification();
    modelProperty.setChangeState(ModelAttribute.ChangeState.DETAIL_CHANGED);
    // Copy the model coordinates to the layout coordinates...
    StringProperty spx;
    if (model instanceof PointModel) {
      spx = (StringProperty) model.getProperty(ElementPropKeys.POINT_POS_X);
    }
    else {
      spx = (StringProperty) model.getProperty(ElementPropKeys.LOC_POS_X);
    }
    spx.setText(String.valueOf(((Number) modelProperty.getValue()).intValue()));
    spx.markChanged();
    cua.snapShotAfterModification();
    undoRedoManager.addEdit(cua);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardQueryService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.QueryResponder;
import org.opentcs.components.kernel.services.InternalQueryService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * The default implementation of the {@link InternalQueryService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardQueryService
    implements InternalQueryService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The responders, by query type.
   */
  private final Map<Class<? extends Query<?>>, QueryResponder> respondersByQueryType
      = new HashMap<>();

  /**
   * Creates a new instance.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   */
  @Inject
  public StandardQueryService(@GlobalSyncObject Object globalSyncObject) {
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
  }

  @Override
  public <T> T query(Query<T> query) {
    requireNonNull(query, "query");

    synchronized (globalSyncObject) {
      QueryResponder responder = respondersByQueryType.get(query.getClass());

      checkArgument(responder != null, "Query class not taken: %s", query.getClass().getName());
      return responder.query(query);
    }
  }

  @Override
  public void registerResponder(@Nonnull Class<? extends Query<?>> clazz,
                                @Nonnull QueryResponder responder) {
    requireNonNull(clazz, "clazz");
    requireNonNull(responder, "responder");

    synchronized (globalSyncObject) {
      checkArgument(!respondersByQueryType.containsKey(clazz),
                    "Query class already taken: %s",
                    clazz.getName());

      respondersByQueryType.put(clazz, responder);
    }
  }

  @Override
  public void unregisterResponder(@Nonnull Class<? extends Query<?>> clazz) {
    requireNonNull(clazz, "clazz");

    synchronized (globalSyncObject) {
      respondersByQueryType.remove(clazz);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/dockable/DockableHandlerFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dockable;

import bibliothek.gui.dock.common.DefaultSingleCDockable;

/**
 * A factory for handlers related to dockables.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface DockableHandlerFactory {

  /**
   * Creates a new handler for closing the given dockable.
   *
   * @param dockable The dockable.
   * @return A new handler for closing the given dockable.
   */
  DockableClosingHandler createDockableClosingHandler(
      DefaultSingleCDockable dockable);
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/kernel/vehicles/StandardVehicleManagerPoolTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import org.junit.*;
import static org.mockito.Mockito.mock;
import org.opentcs.components.kernel.services.InternalVehicleService;
import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;

/**
 * Tests for the {@link StandardVehicleManagerPoolTest}.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardVehicleManagerPoolTest {

  /**
   * A name for a vehicle.
   */
  private static final String A_VEHICLE_NAME = "MyVehicle";
  /**
   * An name for a vehicle that does not exist.
   */
  private static final String UNKNOWN_VEHICLE_NAME = "SomeUnknownVehicle";
  /**
   * The (mocked) vehicle service.
   */
  private InternalVehicleService vehicleService;
  /**
   * A (mocked) communication adapter.
   */
  private VehicleCommAdapter commAdapter;
  /**
   * The VehicleManagerpool we're testing.
   */
  private LocalVehicleControllerPool vehManagerPool;

  @Before
  public void setUp() {
    vehicleService = mock(InternalVehicleService.class);
    commAdapter = mock(VehicleCommAdapter.class);
    vehManagerPool = new DefaultVehicleControllerPool(vehicleService,
                                                      new MockedVehicleManagerFactory());
  }

  @Test(expected = NullPointerException.class)
  public void testThrowsNPEIfVehicleNameIsNull() {
    vehManagerPool.attachVehicleController(null, commAdapter);
  }

  @Test(expected = NullPointerException.class)
  public void testThrowsNPEIfCommAdapterIsNull() {
    vehManagerPool.attachVehicleController(A_VEHICLE_NAME, null);
  }

  @Test(expected = IllegalArgumentException.class)
  public void testThrowsExceptionForUnknownVehicleName() {
    vehManagerPool.attachVehicleController(UNKNOWN_VEHICLE_NAME, commAdapter);
  }

  @Test(expected = NullPointerException.class)
  public void testThrowsNPEIfDetachingNullVehicleName() {
    vehManagerPool.detachVehicleController(null);
  }

  /**
   * A factory delivering vehicle manager mocks.
   */
  private static class MockedVehicleManagerFactory
      implements VehicleControllerFactory {

    @Override
    public DefaultVehicleController createVehicleController(Vehicle vehicle,
                                                            VehicleCommAdapter commAdapter) {
      return mock(DefaultVehicleController.class);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/trigger/ThresholdOrderGenTrigger.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.trigger;

import java.util.LinkedHashSet;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.plugins.panels.loadgenerator.batchcreator.OrderBatchCreator;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Triggers creation of a batch of orders if the number of transport orders
 * in progress drop to or below a given threshold.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ThresholdOrderGenTrigger
    implements EventHandler,
               OrderGenerationTrigger {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ThresholdOrderGenTrigger.class);
  /**
   * Where we get events from.
   */
  private final EventSource eventSource;
  /**
   * The object service we talk to.
   */
  private final TCSObjectService objectService;
  /**
   * The orders that we know are in the system.
   */
  private final Set<TransportOrder> knownOrders = new LinkedHashSet<>();
  /**
   * The threshold for order generation. If the number of orders "in progress"
   * drops to or below this number, a batch of new orders is generated.
   */
  private final int threshold;
  /**
   * The instance actually creating the new orders.
   */
  private final OrderBatchCreator orderBatchCreator;

  /**
   * Creates a new instance.
   *
   * @param eventSource Where this instance registers for events.
   * @param objectService The object service.
   * @param threshold The threshold when new order are being created
   * @param orderBatchCreator The order batch creator
   */
  public ThresholdOrderGenTrigger(final @ApplicationEventBus EventSource eventSource,
                                  final TCSObjectService objectService,
                                  final int threshold,
                                  final OrderBatchCreator orderBatchCreator) {
    this.eventSource = requireNonNull(eventSource, "eventSource");
    this.objectService = requireNonNull(objectService, "objectService");
    this.threshold = threshold;
    this.orderBatchCreator = requireNonNull(orderBatchCreator, "orderBatchCreator");
  }

  @Override
  public void setTriggeringEnabled(boolean enabled) {
    synchronized (knownOrders) {
      if (enabled) {
        // Remember all orders that are not finished, failed etc.
        for (TransportOrder curOrder : objectService.fetchObjects(TransportOrder.class)) {
          if (!curOrder.getState().isFinalState()) {
            knownOrders.add(curOrder);
          }
        }
        eventSource.subscribe(this);
        if (knownOrders.size() <= threshold) {
          triggerOrderGeneration();
        }
      }
      else {
        eventSource.unsubscribe(this);
        knownOrders.clear();
      }
    }
  }

  @Override
  public void triggerOrderGeneration()
      throws KernelRuntimeException {
    knownOrders.addAll(orderBatchCreator.createOrderBatch());
  }

  @Override
  public void onEvent(Object event) {
    if (!(event instanceof TCSObjectEvent)) {
      return;
    }
    TCSObjectEvent objEvent = (TCSObjectEvent) event;
    if (!(objEvent.getCurrentOrPreviousObjectState() instanceof TransportOrder)) {
      return;
    }

    synchronized (knownOrders) {
      TransportOrder eventOrder
          = (TransportOrder) objEvent.getCurrentOrPreviousObjectState();
      // If a new order was created, add it to the set of known orders.
      if (TCSObjectEvent.Type.OBJECT_CREATED.equals(objEvent.getType())) {
        knownOrders.add(eventOrder);
      }
      // If an order was removed, remove it here, too.
      else if (TCSObjectEvent.Type.OBJECT_REMOVED.equals(objEvent.getType())) {
        knownOrders.remove(eventOrder);
      }
      // If an order was modified, check if it's NOT "in progress". If it's not,
      // i.e. if it's now finished, failed etc., remove it here, too.
      else if (eventOrder.getState().isFinalState()) {
        knownOrders.remove(eventOrder);
      }
      // Now let's check if the number of orders "in progress" has dropped below
      // the threshold. If so, create a new batch of orders.
      if (knownOrders.size() <= threshold) {
        LOG.debug("orderCount = " + knownOrders.size() + ", triggering...");
        trigger();
      }
    }
  }

  private void trigger() {
    try {
      triggerOrderGeneration();
    }
    catch (KernelRuntimeException exc) {
      LOG.warn("Exception triggering order generation, terminating triggering", exc);
      setTriggeringEnabled(false);

    }
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/PlantModelCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.ModelConstants;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * A transfer object describing a plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PlantModelCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The plant model's points.
   */
  private List<PointCreationTO> points = new LinkedList<>();
  /**
   * The plant model's paths.
   */
  private List<PathCreationTO> paths = new LinkedList<>();
  /**
   * The plant model's location types.
   */
  private List<LocationTypeCreationTO> locationTypes = new LinkedList<>();
  /**
   * The plant model's locations.
   */
  private List<LocationCreationTO> locations = new LinkedList<>();
  /**
   * The plant model's blocks.
   */
  private List<BlockCreationTO> blocks = new LinkedList<>();
  /**
   * The plant model's groups.
   */
  @Deprecated
  private List<GroupCreationTO> groups = new LinkedList<>();
  /**
   * The plant model's vehicles.
   */
  private List<VehicleCreationTO> vehicles = new LinkedList<>();
  /**
   * The plant model's visual layouts.
   */
  private List<VisualLayoutCreationTO> visualLayouts
      = new LinkedList<>(Arrays.asList(defaultVisualLayout()));

  /**
   * Creates a new instance.
   *
   * @param name The name of this plant model.
   */
  public PlantModelCreationTO(String name) {
    super(name);
  }

  @SuppressWarnings("deprecation")
  private PlantModelCreationTO(@Nonnull String name,
                               @Nonnull Map<String, String> properties,
                               @Nonnull List<PointCreationTO> points,
                               @Nonnull List<PathCreationTO> paths,
                               @Nonnull List<LocationTypeCreationTO> locationTypes,
                               @Nonnull List<LocationCreationTO> locations,
                               @Nonnull List<BlockCreationTO> blocks,
                               @Nonnull List<GroupCreationTO> groups,
                               @Nonnull List<VehicleCreationTO> vehicles,
                               @Nonnull List<VisualLayoutCreationTO> visualLayouts) {
    super(name, properties);
    this.points = requireNonNull(points, "points");
    this.paths = requireNonNull(paths, "paths");
    this.locationTypes = requireNonNull(locationTypes, "locationTypes");
    this.locations = requireNonNull(locations, "locations");
    this.blocks = requireNonNull(blocks, "blocks");
    this.groups = requireNonNull(groups, "groups");
    this.vehicles = requireNonNull(vehicles, "vehicles");
    this.visualLayouts = requireNonNull(visualLayouts, "visualLayouts");
  }

  /**
   * Returns this plant model's points.
   *
   * @return This plant model's points.
   */
  public List<PointCreationTO> getPoints() {
    return Collections.unmodifiableList(points);
  }

  /**
   * Creates a copy of this object with the given points.
   *
   * @param points The new points.
   * @return A copy of this model, differing in the given points.
   */
  public PlantModelCreationTO withPoints(@Nonnull List<PointCreationTO> points) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given point in the list of points.
   *
   * @param point the new point.
   * @return A copy of this model that also includes the given point.
   */
  public PlantModelCreationTO withPoint(@Nonnull PointCreationTO point) {
    requireNonNull(point, "point");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    listWithAppendix(points, point),
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Returns this plant model's paths.
   *
   * @return This plant model's paths.
   */
  public List<PathCreationTO> getPaths() {
    return Collections.unmodifiableList(paths);
  }

  /**
   * Creates a copy of this object with the given paths.
   *
   * @param paths The new paths.
   * @return A copy of this model, differing in the given paths.
   */
  public PlantModelCreationTO withPaths(@Nonnull List<PathCreationTO> paths) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given path in the list of paths.
   *
   * @param path the new path.
   * @return A copy of this model that also includes the given path.
   */
  public PlantModelCreationTO withPath(@Nonnull PathCreationTO path) {
    requireNonNull(path, "path");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    listWithAppendix(paths, path),
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Returns this plant model's location types.
   *
   * @return This plant model's location types.
   */
  public List<LocationTypeCreationTO> getLocationTypes() {
    return Collections.unmodifiableList(locationTypes);
  }

  /**
   * Creates a copy of this object with the given location type.
   *
   * @param locationTypes The new location types.
   * @return A copy of this model, differing in the given location types.
   */
  public PlantModelCreationTO withLocationTypes(@Nonnull List<LocationTypeCreationTO> locationTypes) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given path in the list of location types.
   *
   * @param locationType the new location type.
   * @return A copy of this model that also includes the given location type.
   */
  public PlantModelCreationTO withLocationType(@Nonnull LocationTypeCreationTO locationType) {
    requireNonNull(locationType, "locationType");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    listWithAppendix(locationTypes, locationType),
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Returns this plant model's locations.
   *
   * @return This plant model's locations.
   */
  public List<LocationCreationTO> getLocations() {
    return Collections.unmodifiableList(locations);
  }

  /**
   * Creates a copy of this object with the given locations.
   *
   * @param locations The new locations.
   * @return A copy of this model, differing in the given locations.
   */
  public PlantModelCreationTO withLocations(@Nonnull List<LocationCreationTO> locations) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given block in the list of locations.
   *
   * @param location the new location.
   * @return A copy of this model that also includes the given location.
   */
  public PlantModelCreationTO withLocation(@Nonnull LocationCreationTO location) {
    requireNonNull(location, "location");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    listWithAppendix(locations, location),
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Returns this plant model's blocks.
   *
   * @return This plant model's blocks.
   */
  public List<BlockCreationTO> getBlocks() {
    return Collections.unmodifiableList(blocks);
  }

  /**
   * Creates a copy of this object with the given blocks.
   *
   * @param blocks The new blocks.
   * @return A copy of this model, differing in the given blocks.
   */
  public PlantModelCreationTO withBlocks(@Nonnull List<BlockCreationTO> blocks) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given block in the list of blocks.
   *
   * @param block the new block.
   * @return A copy of this model that also includes the given block.
   */
  public PlantModelCreationTO withBlock(@Nonnull BlockCreationTO block) {
    requireNonNull(block, "block");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    CreationTO.listWithAppendix(blocks, block),
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Returns this plant model's groups.
   *
   * @return This plant model's groups.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public List<GroupCreationTO> getGroups() {
    return Collections.unmodifiableList(groups);
  }

  /**
   * Creates a copy of this object with the given groups.
   *
   * @param groups The new groups.
   * @return A copy of this model, differing in the given groups.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public PlantModelCreationTO withGroups(@Nonnull List<GroupCreationTO> groups) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given group in the list of groups.
   *
   * @param group the new group.
   * @return A copy of this model that also includes the given group.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public PlantModelCreationTO withGroup(@Nonnull GroupCreationTO group) {
    requireNonNull(group, "group");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations, blocks,
                                    listWithAppendix(groups, group),
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Returns this plant model's vehicles.
   *
   * @return This plant model's vehicles.
   */
  public List<VehicleCreationTO> getVehicles() {
    return Collections.unmodifiableList(vehicles);
  }

  /**
   * Creates a copy of this object with the given vehicles.
   *
   * @param vehicles The new vehicles.
   * @return A copy of this model, differing in the given vehicles.
   */
  public PlantModelCreationTO withVehicles(@Nonnull List<VehicleCreationTO> vehicles) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given vehicle in the list of vehicles.
   *
   * @param vehicle the new vehicle.
   * @return A copy of this model that also includes the given vehicle.
   */
  public PlantModelCreationTO withVehicle(@Nonnull VehicleCreationTO vehicle) {
    requireNonNull(vehicle, "vehicle");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    listWithAppendix(vehicles, vehicle),
                                    visualLayouts);
  }

  /**
   * Returns this plant model's visual layout.
   *
   * @return This plant model's visual layout.
   */
  public VisualLayoutCreationTO getVisualLayout() {
    return visualLayouts.get(visualLayouts.size() - 1);
  }

  /**
   * Returns this plant model's visual layouts.
   *
   * @return This plant model's visual layouts.
   * @deprecated Use{@link #getVisualLayout()} instead.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public List<VisualLayoutCreationTO> getVisualLayouts() {
    return Collections.unmodifiableList(visualLayouts);
  }

  /**
   * Creates a copy of this object with the given visual layouts.
   *
   * @param visualLayouts The new visual layouts.
   * @return A copy of this model, differing in the given visual layouts.
   * @deprecated Use {@link #withVisualLayout(org.opentcs.access.to.model.VisualLayoutCreationTO)}
   * instead
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public PlantModelCreationTO withVisualLayouts(@Nonnull List<VisualLayoutCreationTO> visualLayouts) {
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object that includes the given visual layout in the list of
   * visual layout elements.
   *
   * @param visualLayout the new visual layout.
   * @return A copy of this model that also includes the given visual layout.
   */
  @ScheduledApiChange(details = "A plant model will contain only a single visual layout.",
                      when = "6.0")
  public PlantModelCreationTO withVisualLayout(@Nonnull VisualLayoutCreationTO visualLayout) {
    requireNonNull(visualLayout, "visualLayout");
    return new PlantModelCreationTO(getName(),
                                    getModifiableProperties(),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    listWithAppendix(visualLayouts, visualLayout));
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public PlantModelCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new PlantModelCreationTO(getName(),
                                    properties,
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public PlantModelCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new PlantModelCreationTO(getName(),
                                    propertiesWith(key, value),
                                    points,
                                    paths,
                                    locationTypes,
                                    locations,
                                    blocks,
                                    groups,
                                    vehicles,
                                    visualLayouts);
  }

  @Override
  public String toString() {
    return "PlantModelCreationTO{"
        + "name=" + getName()
        + ", points=" + points
        + ", paths=" + paths
        + ", locationTypes=" + locationTypes
        + ", locations=" + locations
        + ", blocks=" + blocks
        + ", groups=" + groups
        + ", vehicles=" + vehicles
        + ", visualLayouts=" + visualLayouts
        + ", properties=" + getProperties()
        + '}';
  }

  private VisualLayoutCreationTO defaultVisualLayout() {
    return new VisualLayoutCreationTO(ModelConstants.DEFAULT_VISUAL_LAYOUT_NAME)
        .withLayer(new Layer(ModelConstants.DEFAULT_LAYER_ID,
                             ModelConstants.DEFAULT_LAYER_ORDINAL,
                             true,
                             ModelConstants.DEFAULT_LAYER_NAME,
                             ModelConstants.DEFAULT_LAYER_GROUP_ID))
        .withLayerGroup(new LayerGroup(ModelConstants.DEFAULT_LAYER_GROUP_ID,
                                       ModelConstants.DEFAULT_LAYER_GROUP_NAME,
                                       true));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/PeripheralDispatcherService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.PeripheralJobDispatcher;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;

/**
 * Provides methods concerning the {@link PeripheralJobDispatcher}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralDispatcherService {

  /**
   * Explicitly trigger the dispatching process for peripheral jobs.
   *
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void dispatch()
      throws KernelRuntimeException;

  /**
   * Withdraw any order that a peripheral device (represented by the given location) might be
   * processing.
   *
   * @param ref A reference to the location representing the peripheral device.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void withdrawByLocation(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException;
}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/main/java/org/opentcs/guing/plugins/panels/statistics/I18nPlantOverviewPanelStatistics.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.statistics;

/**
 * Defines constants regarding internationalization.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface I18nPlantOverviewPanelStatistics {

  /**
   * The path to the project's resource bundle.
   */
  String BUNDLE_PATH = "i18n/org/opentcs/plantoverview/statisticsPanel/Bundle";
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralAdapterPanelComponentsFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

/**
 * A factory for creating various comm adapter panel-specific instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LoopbackPeripheralAdapterPanelComponentsFactory {

  /**
   * Creates a {@link LoopbackPeripheralCommAdapterPanel} representing the given process model's
   * content.
   *
   * @param processModel The process model to represent.
   * @return The comm adapter panel.
   */
  LoopbackPeripheralCommAdapterPanel createPanel(LoopbackPeripheralProcessModel processModel);
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardNotificationService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.function.Predicate;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.notification.UserNotification;
import org.opentcs.kernel.workingset.NotificationBuffer;

/**
 * This class is the standard implementation of the {@link NotificationService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardNotificationService
    implements NotificationService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The buffer for all messages published.
   */
  private final NotificationBuffer notificationBuffer;

  /**
   * Creates a new instance.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param notificationBuffer The notification buffer to be used.
   */
  @Inject
  public StandardNotificationService(@GlobalSyncObject Object globalSyncObject,
                                     NotificationBuffer notificationBuffer) {
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.notificationBuffer = requireNonNull(notificationBuffer, "notificationBuffer");
  }

  @Override
  public List<UserNotification> fetchUserNotifications(Predicate<UserNotification> predicate) {
    synchronized (globalSyncObject) {
      return notificationBuffer.getNotifications(predicate);
    }
  }

  @Override
  public void publishUserNotification(UserNotification notification) {
    synchronized (globalSyncObject) {
      notificationBuffer.addNotification(notification);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/PeripheralOperationModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.peripherals.PeripheralOperation;

/**
 * A Bean to hold the Peripheral operation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralOperationModel {

  /**
   * The operation to be performed by the peripheral device.
   */
  private final String operation;
  /**
   * The name of the location the peripheral device is associated with.
   */
  @Nonnull
  private final String locationName;
  /**
   * The moment at which this operation is to be performed.
   */
  @Nonnull
  private final PeripheralOperation.ExecutionTrigger executionTrigger;
  /**
   * Whether the completion of this operation is required to allow a vehicle to continue driving.
   */
  private final boolean completionRequired;

  public PeripheralOperationModel(String locationName,
                                  String operation,
                                  PeripheralOperation.ExecutionTrigger executionTrigger,
                                  boolean completionRequired) {
    this.operation = requireNonNull(operation, "operation");
    this.locationName = requireNonNull(locationName, "locationName");
    this.executionTrigger = requireNonNull(executionTrigger, "executionTrigger");
    this.completionRequired = requireNonNull(completionRequired, "completionRequired");
  }

  public String getOperation() {
    return operation;
  }

  public String getLocationName() {
    return locationName;
  }

  public PeripheralOperation.ExecutionTrigger getExecutionTrigger() {
    return executionTrigger;
  }

  public boolean isCompletionRequired() {
    return completionRequired;
  }

}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/main/java/org/opentcs/guing/plugins/panels/statistics/package-info.java<|end_filename|>
/**
 * A plugin panel providing a statistics report based on dump file data.
 */
package org.opentcs.guing.plugins.panels.statistics;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/ProgressStatus.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

/**
 * A state of progress, to be used with {@link ProgressIndicator}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ProgressStatus {

  /**
   * Returns a percentage value.
   *
   * @return A percentage value, greater than or equal to 0 and less than or equal to 100.
   */
  int getPercentage();

  /**
   * Returns a (possibly localized) description of the current status to be displayed.
   *
   * @return A description of the current status to be displayed.
   */
  String getStatusDescription();
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/persistence/unified/PlantModelElementConverter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence.unified;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import org.opentcs.access.to.model.BlockCreationTO;
import org.opentcs.access.to.model.LocationCreationTO;
import org.opentcs.access.to.model.LocationTypeCreationTO;
import org.opentcs.access.to.model.PathCreationTO;
import org.opentcs.access.to.model.PointCreationTO;
import org.opentcs.access.to.model.VehicleCreationTO;
import org.opentcs.access.to.model.VisualLayoutCreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.data.model.Block;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.components.properties.type.AngleProperty;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.PercentProperty;
import org.opentcs.guing.components.properties.type.SpeedProperty;
import org.opentcs.guing.model.PeripheralOperationModel;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PlantModelElementConverter {

  public PlantModelElementConverter() {
  }

  public PointModel importPoint(PointCreationTO pointTO, SystemModel systemModel) {
    requireNonNull(pointTO, "pointTO");
    requireNonNull(systemModel, "systemModel");

    PointModel model = new PointModel();

    model.setName(pointTO.getName());

    model.getPropertyModelPositionX().setValueAndUnit(pointTO.getPosition().getX(),
                                                      LengthProperty.Unit.MM);
    model.getPropertyModelPositionY().setValueAndUnit(pointTO.getPosition().getY(),
                                                      LengthProperty.Unit.MM);
    model.getPropertyVehicleOrientationAngle().setValueAndUnit(pointTO.getVehicleOrientationAngle(),
                                                               AngleProperty.Unit.DEG);
    model.getPropertyType().setValue(mapPointType(pointTO.getType()));
    for (Map.Entry<String, String> property : pointTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    // Gather information contained in the layout
    model.getPropertyLayoutPosX().setText(String.valueOf(pointTO.getLayout().getPosition().getX()));
    model.getPropertyLayoutPosY().setText(String.valueOf(pointTO.getLayout().getPosition().getY()));
    model.getPropertyPointLabelOffsetX().setText(String.valueOf(pointTO.getLayout().getLabelOffset().getX()));
    model.getPropertyPointLabelOffsetY().setText(String.valueOf(pointTO.getLayout().getLabelOffset().getY()));
    model.getPropertyPointLabelOrientationAngle().setText("");
    LayerWrapper layerWrapper = systemModel.getLayoutModel().getPropertyLayerWrappers()
        .getValue().get(pointTO.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);

    return model;
  }

  public PathModel importPath(PathCreationTO pathTO, SystemModel systemModel) {
    PathModel model = new PathModel();

    model.setName(pathTO.getName());
    model.getPropertyLength().setValueAndUnit(pathTO.getLength(), LengthProperty.Unit.MM);
    model.getPropertyMaxVelocity().setValueAndUnit(pathTO.getMaxVelocity(),
                                                   SpeedProperty.Unit.MM_S);
    model.getPropertyMaxReverseVelocity().setValueAndUnit(pathTO.getMaxReverseVelocity(),
                                                          SpeedProperty.Unit.MM_S);
    model.getPropertyStartComponent().setText(pathTO.getSrcPointName());
    model.getPropertyEndComponent().setText(pathTO.getDestPointName());
    model.getPropertyLocked().setValue(pathTO.isLocked());

    for (Map.Entry<String, String> property : pathTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    for (PeripheralOperationCreationTO operationTO : pathTO.getPeripheralOperations()) {
      model.getPropertyPeripheralOperations().getValue().add(
          new PeripheralOperationModel(operationTO.getLocationName(),
                                       operationTO.getOperation(),
                                       operationTO.getExecutionTrigger(),
                                       operationTO.isCompletionRequired())
      );
    }

    // Gather information contained in the layout
    model.getPropertyPathConnType()
        .setValue(PathModel.Type.valueOf(pathTO.getLayout().getConnectionType().name()));
    model.getPropertyPathControlPoints().setText(
        pathTO.getLayout().getControlPoints().stream()
            .map(controlPoint -> String.format("%d,%d", controlPoint.getX(), controlPoint.getY()))
            .collect(Collectors.joining(";"))
    );
    LayerWrapper layerWrapper = systemModel.getLayoutModel().getPropertyLayerWrappers()
        .getValue().get(pathTO.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);

    return model;
  }

  public VehicleModel importVehicle(VehicleCreationTO vehicleTO) {
    VehicleModel model = new VehicleModel();

    model.setName(vehicleTO.getName());
    model.getPropertyLength().setValueAndUnit(vehicleTO.getLength(), LengthProperty.Unit.MM);
    model.getPropertyMaxVelocity().setValueAndUnit(((double) vehicleTO.getMaxVelocity()),
                                                   SpeedProperty.Unit.MM_S);
    model.getPropertyMaxReverseVelocity().setValueAndUnit(
        ((double) vehicleTO.getMaxReverseVelocity()), SpeedProperty.Unit.MM_S);
    model.getPropertyEnergyLevelCritical().setValueAndUnit(vehicleTO.getEnergyLevelCritical(),
                                                           PercentProperty.Unit.PERCENT);
    model.getPropertyEnergyLevelGood().setValueAndUnit(vehicleTO.getEnergyLevelGood(),
                                                       PercentProperty.Unit.PERCENT);
    model.getPropertyEnergyLevelFullyRecharged().setValueAndUnit(
        vehicleTO.getEnergyLevelFullyRecharged(), PercentProperty.Unit.PERCENT
    );
    model.getPropertyEnergyLevelSufficientlyRecharged().setValueAndUnit(
        vehicleTO.getEnergyLevelSufficientlyRecharged(), PercentProperty.Unit.PERCENT
    );
    for (Map.Entry<String, String> property : vehicleTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    // Gather information contained in the layout
    model.getPropertyRouteColor().setColor(vehicleTO.getLayout().getRouteColor());

    return model;
  }

  public LocationTypeModel importLocationType(LocationTypeCreationTO locTypeTO) {
    LocationTypeModel model = new LocationTypeModel();

    model.setName(locTypeTO.getName());
    for (String allowedOperation : locTypeTO.getAllowedOperations()) {
      model.getPropertyAllowedOperations().addItem(allowedOperation);
    }

    for (String allowedPeripheralOperations : locTypeTO.getAllowedPeripheralOperations()) {
      model.getPropertyAllowedPeripheralOperations().addItem(allowedPeripheralOperations);
    }

    for (Map.Entry<String, String> property : locTypeTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    // Gather information contained in the layout
    model.getPropertyDefaultRepresentation().setLocationRepresentation(
        LocationRepresentation.valueOf(locTypeTO.getLayout().getLocationRepresentation().name())
    );

    return model;
  }

  public LocationModel importLocation(LocationCreationTO locationTO,
                                      Collection<LocationTypeCreationTO> locTypes,
                                      SystemModel systemModel) {
    LocationModel model = new LocationModel();

    model.setName(locationTO.getName());
    model.getPropertyModelPositionX().setValueAndUnit(locationTO.getPosition().getX(),
                                                      LengthProperty.Unit.MM);
    model.getPropertyModelPositionY().setValueAndUnit(locationTO.getPosition().getY(),
                                                      LengthProperty.Unit.MM);

    List<String> possibleLocationTypes = new ArrayList<>();
    for (LocationTypeCreationTO locType : locTypes) {
      if (!possibleLocationTypes.contains(locType.getName())) {
        possibleLocationTypes.add(locType.getName());
      }
    }
    model.getPropertyType().setPossibleValues(possibleLocationTypes);
    model.getPropertyType().setValue(locationTO.getTypeName());
    model.getPropertyLocked().setValue(locationTO.isLocked());

    for (Map.Entry<String, String> property : locationTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    // Gather information contained in the layout
    model.getPropertyLayoutPositionX().setText(String.valueOf(locationTO.getLayout().getPosition().getX()));
    model.getPropertyLayoutPositionY().setText(String.valueOf(locationTO.getLayout().getPosition().getY()));
    model.getPropertyLabelOffsetX().setText(String.valueOf(locationTO.getLayout().getLabelOffset().getX()));
    model.getPropertyLabelOffsetY().setText(String.valueOf(locationTO.getLayout().getLabelOffset().getY()));
    model.getPropertyDefaultRepresentation().setLocationRepresentation(
        LocationRepresentation.valueOf(locationTO.getLayout().getLocationRepresentation().name())
    );
    model.getPropertyLabelOrientationAngle().setText("");
    LayerWrapper layerWrapper = systemModel.getLayoutModel().getPropertyLayerWrappers()
        .getValue().get(locationTO.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);

    return model;
  }

  public LinkModel importLocationLink(LocationCreationTO locationTO,
                                      String pointName,
                                      Set<String> operations,
                                      SystemModel systemModel) {
    LinkModel model = new LinkModel();

    model.setName(String.format("%s --- %s", pointName, locationTO.getName()));

    for (String operation : operations) {
      model.getPropertyAllowedOperations().addItem(operation);
    }

    model.getPropertyStartComponent().setText(pointName);
    model.getPropertyEndComponent().setText(locationTO.getName());
    LayerWrapper layerWrapper = systemModel.getLayoutModel().getPropertyLayerWrappers()
        .getValue().get(locationTO.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);

    return model;
  }

  public BlockModel importBlock(BlockCreationTO blockTO) {
    BlockModel model = new BlockModel();

    model.setName(blockTO.getName());

    model.getPropertyType().setValue(mapBlockType(blockTO.getType()));

    for (String member : blockTO.getMemberNames()) {
      model.getPropertyElements().addItem(member);
    }

    for (Map.Entry<String, String> property : blockTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    // Gather information contained in the layout
    model.getPropertyColor().setColor(blockTO.getLayout().getColor());

    return model;
  }

  public LayoutModel importLayout(VisualLayoutCreationTO layoutTO) {
    LayoutModel model = new LayoutModel();

    model.setName(layoutTO.getName());
    model.getPropertyScaleX().setValueAndUnit(layoutTO.getScaleX(), LengthProperty.Unit.MM);
    model.getPropertyScaleY().setValueAndUnit(layoutTO.getScaleY(), LengthProperty.Unit.MM);
    initLayerGroups(model, layoutTO.getLayerGroups());
    initLayers(model, layoutTO.getLayers());

    for (Map.Entry<String, String> property : layoutTO.getProperties().entrySet()) {
      model.getPropertyMiscellaneous().addItem(new KeyValueProperty(model,
                                                                    property.getKey(),
                                                                    property.getValue()));
    }

    return model;
  }

  private PointModel.Type mapPointType(Point.Type type) {
    switch (type) {
      case HALT_POSITION:
        return PointModel.Type.HALT;
      case PARK_POSITION:
        return PointModel.Type.PARK;
      case REPORT_POSITION:
        return PointModel.Type.REPORT;
      default:
        throw new IllegalArgumentException("Unhandled point type: " + type);
    }
  }

  private BlockModel.Type mapBlockType(Block.Type type) {
    switch (type) {
      case SINGLE_VEHICLE_ONLY:
        return BlockModel.Type.SINGLE_VEHICLE_ONLY;
      case SAME_DIRECTION_ONLY:
        return BlockModel.Type.SAME_DIRECTION_ONLY;
      default:
        throw new IllegalArgumentException("Unhandled block type: " + type);
    }
  }

  private void initLayerGroups(LayoutModel model, Collection<LayerGroup> groups) {
    Map<Integer, LayerGroup> layerGroups = model.getPropertyLayerGroups().getValue();
    layerGroups.clear();
    for (LayerGroup group : groups) {
      layerGroups.put(group.getId(), group);
    }
  }

  private void initLayers(LayoutModel model, Collection<Layer> layers) {
    Map<Integer, LayerWrapper> layerWrappers = model.getPropertyLayerWrappers().getValue();
    layerWrappers.clear();

    Map<Integer, LayerGroup> layerGroups = model.getPropertyLayerGroups().getValue();
    for (Layer layer : layers) {
      layerWrappers.put(layer.getId(),
                        new LayerWrapper(layer, layerGroups.get(layer.getGroupId())));
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/DefaultVehicleCommAdapterDescription.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;

/**
 * The default implementation of {@link VehicleCommAdapterDescription}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultVehicleCommAdapterDescription
    extends VehicleCommAdapterDescription {

  /**
   * The description.
   */
  private final String description;
  /**
   * Whether the comm adapter is a simulating one.
   */
  private final boolean isSimVehicleCommAdapter;

  /**
   * Creates a new instance.
   *
   * @param description The description.
   * @param isSimVehicleCommAdapter Whether the comm adapter is a simulating one.
   */
  public DefaultVehicleCommAdapterDescription(@Nonnull String description,
                                              boolean isSimVehicleCommAdapter) {
    this.description = requireNonNull(description, "description");
    this.isSimVehicleCommAdapter = isSimVehicleCommAdapter;
  }

  @Override
  public String getDescription() {
    return description;
  }

  @Override
  public boolean isSimVehicleCommAdapter() {
    return isSimVehicleCommAdapter;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/commands/package-info.java<|end_filename|>
/**
 * Commands a comm adapter may execute.
 */
package org.opentcs.drivers.vehicle.commands;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/peripherals/PeripheralJobCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.peripherals;

import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.access.to.CreationTO;

/**
 * A transfer object describing a peripheral job.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralJobCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * Indicates whether the name is incomplete and requires to be completed when creating the actual
   * peripheral job.
   * (How exactly this is done is decided by the kernel.)
   */
  private final boolean incompleteName;
  /**
   * A token that may be used to reserve a peripheral device.
   * A peripheral device that is reserved for a specific token can only process jobs which match
   * that reservation token.
   * This string may not be empty.
   */
  @Nonnull
  private final String reservationToken;
  /**
   * The name of the vehicle for which this peripheral job is to be created.
   */
  @Nullable
  private final String relatedVehicleName;
  /**
   * The name of the transport order for which this peripheral job is to be created.
   */
  @Nullable
  private final String relatedTransportOrderName;
  /**
   * The operation that is to be perfromed by the pripheral device.
   */
  @Nonnull
  private final PeripheralOperationCreationTO peripheralOperation;

  /**
   * Creates a new instance.
   *
   * @param name The name of this peripheral job.
   * @param reservationToken The reservation token to be used.
   * @param peripheralOperation The peripheral operation to be performed.
   */
  public PeripheralJobCreationTO(@Nonnull String name,
                                 @Nonnull String reservationToken,
                                 @Nonnull PeripheralOperationCreationTO peripheralOperation) {
    super(name);
    this.incompleteName = false;
    this.reservationToken = requireNonNull(reservationToken, "reservationToken");
    this.relatedVehicleName = null;
    this.relatedTransportOrderName = null;
    this.peripheralOperation = requireNonNull(peripheralOperation, "peripheralOperation");
  }

  private PeripheralJobCreationTO(@Nonnull String name,
                                  @Nonnull Map<String, String> properties,
                                  boolean incompleteName,
                                  @Nonnull String reservationToken,
                                  @Nullable String relatedVehicleName,
                                  @Nullable String relatedTransportOrderName,
                                  @Nonnull PeripheralOperationCreationTO peripheralOperation) {
    super(name, properties);
    this.incompleteName = incompleteName;
    this.reservationToken = requireNonNull(reservationToken, "reservationToken");
    this.relatedVehicleName = relatedVehicleName;
    this.relatedTransportOrderName = relatedTransportOrderName;
    this.peripheralOperation = requireNonNull(peripheralOperation, "peripheralOperation");
  }

  @Override
  public PeripheralJobCreationTO withName(@Nonnull String name) {
    return new PeripheralJobCreationTO(name,
                                       getModifiableProperties(),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  @Override
  public PeripheralJobCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new PeripheralJobCreationTO(getName(),
                                       properties,
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  @Override
  public PeripheralJobCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new PeripheralJobCreationTO(getName(),
                                       propertiesWith(key, value),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  /**
   * Indicates whether the name is incomplete and requires to be completed when creating the actual
   * transport order.
   * (How exactly this is done is decided by the kernel.)
   *
   * @return {@code true} if, and only if, the name is incomplete and requires to be completed
   * by the kernel.
   */
  public boolean hasIncompleteName() {
    return incompleteName;
  }

  /**
   * Creates a copy of this object, with the given incomplete name flag.
   *
   * @param incompleteName The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJobCreationTO withIncompleteName(boolean incompleteName) {
    return new PeripheralJobCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  /**
   * Returns the token that may be used to reserve a peripheral device.
   *
   * @return The token that may be used to reserve a peripheral device.
   */
  public String getReservationToken() {
    return reservationToken;
  }

  /**
   * Creates a copy of this object, with the given reservation token.
   *
   * @param reservationToken The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJobCreationTO withReservationToken(String reservationToken) {
    return new PeripheralJobCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  /**
   * Returns the name of the vehicle for which this peripheral job is to be created.
   *
   * @return The name of the vehicle for which this peripheral job is to be created.
   */
  @Nullable
  public String getRelatedVehicleName() {
    return relatedVehicleName;
  }

  /**
   * Creates a copy of this object, with the given related vehicle name.
   *
   * @param relatedVehicleName The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJobCreationTO withRelatedVehicleName(@Nullable String relatedVehicleName) {
    return new PeripheralJobCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  /**
   * Returns the name of the transport order for which this peripheral job is to be created.
   *
   * @return The name of the transport order for which this peripheral job is to be created.
   */
  @Nullable
  public String getRelatedTransportOrderName() {
    return relatedTransportOrderName;
  }

  /**
   * Creates a copy of this object, with the given related transport order name.
   *
   * @param relatedTransportOrderName The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJobCreationTO withRelatedTransportOrderName(
      @Nullable String relatedTransportOrderName) {
    return new PeripheralJobCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }

  /**
   * Returns the operation that is to be performed by the pripheral device.
   *
   * @return The operation that is to be performed by the pripheral device.
   */
  public PeripheralOperationCreationTO getPeripheralOperation() {
    return peripheralOperation;
  }

  /**
   * Creates a copy of this object, with the given peripheral operation.
   *
   * @param peripheralOperation The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJobCreationTO withPeripheralOperation(
      PeripheralOperationCreationTO peripheralOperation) {
    return new PeripheralJobCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       reservationToken,
                                       relatedVehicleName,
                                       relatedTransportOrderName,
                                       peripheralOperation);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/package-info.java<|end_filename|>
/**
 * Basic openTCS data structures.
 */
package org.opentcs.data;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/PluggablePanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.access.Kernel;

/**
 * Produces plugin panels to extend an openTCS user interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PluggablePanelFactory {

  /**
   * Checks whether this factory produces panels that are available in the
   * passed <code>Kernel.State</code>.
   *
   * @param state The kernel state.
   * @return <code>true</code> if, and only if, this factory returns panels that
   * are available in the passed kernel state.
   */
  boolean providesPanel(Kernel.State state);

  /**
   * Returns a string describing the factory/the panels provided.
   * This should be a short string that can be displayed e.g. as a menu item for
   * selecting a factory/plugin panel to be displayed.
   *
   * @return A string describing the factory/the panels provided.
   */
  @Nonnull
  String getPanelDescription();

  /**
   * Returns a newly created panel.
   * If a reference to the kernel provider has not been set, yet, or has been
   * set to <code>null</code>, this method returns <code>null</code>.
   *
   * @param state The kernel state for which to create the panel.
   * @return A newly created panel.
   */
  @Nullable
  PluggablePanel createPanel(Kernel.State state);
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/adminwebapi/v1/V1RequestHandler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.adminwebapi.v1;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.access.LocalKernel;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spark.Request;
import spark.Response;

/**
 * Handles requests and produces responses for version 1 of the admin web API.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V1RequestHandler
    implements Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(V1RequestHandler.class);
  /**
   * Maps between objects and their JSON representations.
   */
  private final ObjectMapper objectMapper
      = new ObjectMapper()
          .registerModule(new JavaTimeModule())
          .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
  /**
   * The local kernel.
   */
  private final LocalKernel kernel;
  /**
   * Used to schedule kernel shutdowns.
   */
  private final ScheduledExecutorService kernelExecutor;
  /**
   * Whether this instance is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param kernel The local kernel.
   * @param kernelExecutor Use to schedule kernel shutdowns.
   */
  @Inject
  public V1RequestHandler(LocalKernel kernel,
                          @KernelExecutor ScheduledExecutorService kernelExecutor) {
    this.kernel = requireNonNull(kernel, "kernel");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    initialized = false;
  }

  public Object handleGetVersion(Request request, Response response) {
    return toJson(new Version());
  }

  public Object handleGetStatus(Request request, Response response) {
    return toJson(new Status());
  }

  public Object handleDeleteKernel(Request request, Response response) {
    LOG.info("Initiating kernel shutdown as requested from {}...", request.ip());
    kernelExecutor.schedule(() -> kernel.setState(Kernel.State.SHUTDOWN), 1, TimeUnit.SECONDS);
    return "";
  }

  private <T> T fromJson(String jsonString, Class<T> clazz)
      throws IllegalArgumentException {
    try {
      return objectMapper.readValue(jsonString, clazz);
    }
    catch (IOException exc) {
      throw new IllegalArgumentException("Could not parse JSON input", exc);
    }
  }

  private String toJson(Object object)
      throws IllegalStateException {
    try {
      return objectMapper
          .writerWithDefaultPrettyPrinter()
          .writeValueAsString(object);
    }
    catch (JsonProcessingException exc) {
      throw new IllegalStateException("Could not produce JSON output", exc);
    }
  }

}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/Environment.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides generic information about the openTCS environment.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class Environment {

  /**
   * The baseline properties file.
   */
  private static final String BASELINE_PROPS_FILE = "/opentcs.properties";
  /**
   * The customization properties file.
   */
  private static final String CUSTOMIZATION_PROPS_FILE = "/opentcs-customization.properties";
  /**
   * The openTCS baseline version as a string.
   */
  private static final String BASELINE_VERSION;
  /**
   * The build date of the openTCS baseline as a string.
   */
  private static final String BASELINE_BUILD_DATE;
  /**
   * The name of the customized distribution.
   */
  private static final String CUSTOMIZATION_NAME;
  /**
   * The version of the customized distribution as a string.
   */
  private static final String CUSTOMIZATION_VERSION;
  /**
   * The build date of the customized distribution as a string.
   */
  private static final String CUSTOMIZATION_BUILD_DATE;
  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(Environment.class);

  static {
    Properties props = new Properties();
    try {
      InputStream inStream = Environment.class.getResourceAsStream(BASELINE_PROPS_FILE);
      if (inStream != null) {
        props.load(inStream);
      }
      inStream = Environment.class.getResourceAsStream(CUSTOMIZATION_PROPS_FILE);
      if (inStream != null) {
        props.load(inStream);
      }
    }
    catch (IOException exc) {
      throw new IllegalStateException("Could not load environment properties", exc);
    }
    BASELINE_VERSION = props.getProperty("opentcs.version", "unknown version");
    BASELINE_BUILD_DATE = props.getProperty("opentcs.builddate", "unknown build date");
    CUSTOMIZATION_NAME = props.getProperty("opentcs.customization.name", "-");
    CUSTOMIZATION_VERSION = props.getProperty("opentcs.customization.version", "-");
    CUSTOMIZATION_BUILD_DATE = props.getProperty("opentcs.customization.builddate", "-");
  }

  /**
   * Prevents undesired instantiation.
   */
  private Environment() {
  }

  /**
   * Returns the version of openTCS (i.e. the base library) as a string.
   *
   * @return The version of openTCS (i.e. the base library) as a string.
   */
  public static String getBaselineVersion() {
    return BASELINE_VERSION;
  }

  /**
   * Returns the build date of openTCS (i.e. the base library) as a string.
   *
   * @return The build date of openTCS (i.e. the base library) as a string.
   */
  public static String getBaselineBuildDate() {
    return BASELINE_BUILD_DATE;
  }

  /**
   * Returns the name of the customized distribution.
   *
   * @return The name of the customized distribution.
   */
  public static String getCustomizationName() {
    return CUSTOMIZATION_NAME;
  }

  /**
   * Returns the version of the customized distribution as a string.
   *
   * @return The version of the customized distribution as a string.
   */
  public static String getCustomizationVersion() {
    return CUSTOMIZATION_VERSION;
  }

  /**
   * Returns the build date of the customized distribution as a string.
   *
   * @return The build date of the customized distribution as a string.
   */
  public static String getCustomizationBuildDate() {
    return CUSTOMIZATION_BUILD_DATE;
  }

  /**
   * Write information about the OpenTCS version, the operating system and
   * the running Java VM to the log.
   */
  public static void logSystemInfo() {
    LOG.info("openTCS baseline version: {} (build date: {}), "
        + "customization '{}' version {} (build date: {}), "
        + "Java: {}, {}; JVM: {}, {}; OS: {}, {}",
             BASELINE_VERSION,
             BASELINE_BUILD_DATE,
             CUSTOMIZATION_NAME,
             CUSTOMIZATION_VERSION,
             CUSTOMIZATION_BUILD_DATE,
             System.getProperty("java.version"),
             System.getProperty("java.vendor"),
             System.getProperty("java.vm.version"),
             System.getProperty("java.vm.vendor"),
             System.getProperty("os.name"),
             System.getProperty("os.arch"));
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/DefaultJobSelectionStrategy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import org.opentcs.data.model.Location;
import org.opentcs.data.peripherals.PeripheralJob;
import static org.opentcs.util.Assertions.checkArgument;
import org.opentcs.util.Comparators;

/**
 * The default implementation of {@link JobSelectionStrategy}.
 * Selects a job by applying the following rules:
 * <ul>
 * <li>The location of a job's operation has to match the given location.</li>
 * <li>If this applies to multiple jobs, the oldest one is selected.</li>
 * </ul>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultJobSelectionStrategy
    implements JobSelectionStrategy {

  @Override
  public Optional<PeripheralJob> select(Collection<PeripheralJob> jobs, Location location) {
    checkArgument(jobs.stream().allMatch(job -> matchesLocation(job, location)),
                  "All jobs are expected to match the given location: %s", location.getName());

    return jobs.stream()
        .sorted(Comparators.jobsByAge())
        .findFirst();
  }

  private boolean matchesLocation(PeripheralJob job, Location location) {
    return Objects.equals(job.getPeripheralOperation().getLocation(), location.getReference());
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/CompositeVehicleCandidateComparator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization;

import com.google.common.collect.Lists;
import java.util.Comparator;
import java.util.Map;
import javax.inject.Inject;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByEnergyLevel;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByVehicleName;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A composite of all configured vehicle candidate comparators.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeVehicleCandidateComparator
    implements Comparator<AssignmentCandidate> {

  /**
   * A comparator composed of all configured comparators, in the configured order.
   */
  private final Comparator<AssignmentCandidate> compositeComparator;

  @Inject
  public CompositeVehicleCandidateComparator(
      DefaultDispatcherConfiguration configuration,
      Map<String, Comparator<AssignmentCandidate>> availableComparators) {
    // At the end, if all other comparators failed to see a difference, compare by energy level.
    // As the energy level of two distinct vehicles may still be the same, finally compare by name.
    // Add configured comparators before these two.
    Comparator<AssignmentCandidate> composite
        = new CandidateComparatorByEnergyLevel()
            .thenComparing(new CandidateComparatorByVehicleName());

    for (String priorityKey : Lists.reverse(configuration.vehicleCandidatePriorities())) {
      Comparator<AssignmentCandidate> configuredComparator = availableComparators.get(priorityKey);
      checkArgument(configuredComparator != null,
                    "Unknown vehicle candidate priority key: %s",
                    priorityKey);
      composite = configuredComparator.thenComparing(composite);
    }
    this.compositeComparator = composite;
  }

  @Override
  public int compare(AssignmentCandidate o1, AssignmentCandidate o2) {
    return compositeComparator.compare(o1, o2);
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/orders/TransportOrderTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.orders;

import java.time.Instant;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.Vector;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A table model for transport orders.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderTableModel
    extends AbstractTableModel
    implements TransportOrderContainerListener {

  private static final Logger LOG = LoggerFactory.getLogger(TransportOrderTableModel.class);
  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewOperating.TRANSPORTORDER_PATH);

  public static final int COLUMN_NAME = 0;
  public static final int COLUMN_SOURCE = 1;
  public static final int COLUMN_DESTINATION = 2;
  public static final int COLUMN_INTENDED_VEHICLE = 3;
  public static final int COLUMN_EXECUTING_VEHICLE = 4;
  public static final int COLUMN_STATUS = 5;
  public static final int COLUMN_ORDER_SEQUENCE = 6;
  public static final int COLUMN_CREATION_TIME = 7;

  private static final String[] COLUMN_NAMES = new String[]{
    "Name",
    BUNDLE.getString("transportOrderTableModel.column_source.headerText"),
    BUNDLE.getString("transportOrderTableModel.column_destination.headerText"),
    BUNDLE.getString("transportOrderTableModel.column_intendedVehicle.headerText"),
    BUNDLE.getString("transportOrderTableModel.column_executingVehicle.headerText"),
    "Status",
    BUNDLE.getString("transportOrderTableModel.column_orderSequence.headerText"),
    BUNDLE.getString("transportOrderTableModel.column_creationTime.headerText")
  };

  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
    String.class,
    String.class,
    String.class,
    String.class,
    String.class,
    String.class,
    String.class,
    Instant.class
  };

  private final List<TransportOrder> entries = new LinkedList<>();

  @Override
  public int getRowCount() {
    return entries.size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= getRowCount()) {
      return null;
    }

    TransportOrder entry = entries.get(rowIndex);
    Vector<DriveOrder> driveOrders = new Vector<>(entry.getAllDriveOrders());
    switch (columnIndex) {
      case COLUMN_NAME:
        return entry.getName();
      case COLUMN_SOURCE:
        if (driveOrders.size() == 1) {
          return "";
        }
        else {
          return driveOrders.firstElement().getDestination().getDestination().getName();
        }
      case COLUMN_DESTINATION:
        return driveOrders.lastElement().getDestination().getDestination().getName();
      case COLUMN_INTENDED_VEHICLE:
        if (entry.getIntendedVehicle() != null) {
          return entry.getIntendedVehicle().getName();
        }
        else {
          return BUNDLE.getString("transportOrderTableModel.column_intendedVehicle.determinedAutomatic.text");
        }
      case COLUMN_EXECUTING_VEHICLE:
        if (entry.getProcessingVehicle() != null) {
          return entry.getProcessingVehicle().getName();
        }
        else {
          return "?";
        }
      case COLUMN_STATUS:
        return entry.getState().toString();
      case COLUMN_ORDER_SEQUENCE:
        if (entry.getWrappingSequence() != null) {
          return entry.getWrappingSequence().getName();
        }
        else {
          return "-";
        }
      case COLUMN_CREATION_TIME:
        return entry.getCreationTime();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public void containerInitialized(Collection<TransportOrder> orders) {
    requireNonNull(orders, "orders");

    SwingUtilities.invokeLater(() -> {
      // Notifiations of any change listeners must happen at the same time/in the same thread the 
      // data behind the model is updated. Otherwise, there is a risk that listeners work with/
      // refer to outdated data, which can lead to runtime exceptions.
      entries.clear();
      entries.addAll(orders);
      fireTableDataChanged();
    });
  }

  @Override
  public void transportOrderAdded(TransportOrder order) {
    requireNonNull(order, "order");

    SwingUtilities.invokeLater(() -> {
      entries.add(order);
      fireTableRowsInserted(entries.size() - 1, entries.size() - 1);
    });
  }

  @Override
  public void transportOrderUpdated(TransportOrder order) {
    requireNonNull(order, "order");

    SwingUtilities.invokeLater(() -> {
      int orderIndex = entries.indexOf(order);
      if (orderIndex == -1) {
        LOG.warn("Unknown transport order: {}. Ignoring order update.", order.getName());
        return;
      }
      entries.set(orderIndex, order);
      fireTableRowsUpdated(orderIndex, orderIndex);
    });
  }

  @Override
  public void transportOrderRemoved(TransportOrder order) {
    requireNonNull(order, "order");

    SwingUtilities.invokeLater(() -> {
      int orderIndex = entries.indexOf(order);
      if (orderIndex == -1) {
        LOG.warn("Unknown transport order: {}. Ignoring order removal.", order.getName());
        return;
      }
      entries.remove(orderIndex);
      fireTableRowsDeleted(orderIndex, orderIndex);
    });

  }

  /**
   * Returns the transport order at the specified index.
   *
   * @param index the index to return.
   * @return the transport order at that index.
   */
  public TransportOrder getEntryAt(int index) {
    if (index < 0 || index >= entries.size()) {
      return null;
    }

    return entries.get(index);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteQueryServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.services.QueryService;

/**
 * The default implementation of the query service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RemoteQueryServiceProxy
    extends AbstractRemoteServiceProxy<RemoteQueryService>
    implements QueryService {

  @Override
  public <T> T query(Query<T> query) {
    checkServiceAvailability();

    try {
      return getRemoteService().query(getClientId(), query);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/order/DestinationCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.order;

import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;

/**
 * A transfer object describing a destination of a drive order.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DestinationCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The name of the destination location (or point).
   */
  @Nonnull
  private String destLocationName;
  /**
   * The operation to be performed at the destination.
   */
  @Nonnull
  private String destOperation;

  /**
   * Creates a new instance.
   *
   * @param destLocationName The name of the destination location (or destination point).
   * @param destOperation The operation to be performed at the destination.
   */
  public DestinationCreationTO(@Nonnull String destLocationName,
                               @Nonnull String destOperation) {
    super("");
    this.destLocationName = requireNonNull(destLocationName, "destLocationName");
    this.destOperation = requireNonNull(destOperation, "destOperation");
  }

  private DestinationCreationTO(@Nonnull String destLocationName,
                                @Nonnull String destOperation,
                                @Nonnull String name,
                                @Nonnull Map<String, String> properties) {
    super(name, properties);
    this.destLocationName = requireNonNull(destLocationName, "destLocationName");
    this.destOperation = requireNonNull(destOperation, "destOperation");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name the new name of the instance.
   * @return A copy of this object, differing in the given value.
   */
  @Override
  public DestinationCreationTO withName(@Nonnull String name) {
    return new DestinationCreationTO(destLocationName, destOperation, name, getModifiableProperties());
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given value.
   */
  @Override
  public DestinationCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new DestinationCreationTO(destLocationName, destOperation, getName(), properties);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public DestinationCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new DestinationCreationTO(destLocationName,
                                     destOperation,
                                     getName(),
                                     propertiesWith(key, value));
  }

  /**
   * Returns the destination location (or point) name.
   *
   * @return The destination location (or point) name.
   */
  @Nonnull
  public String getDestLocationName() {
    return destLocationName;
  }

  /**
   * Creates a copy of this object with the given destination location (or point) name.
   *
   * @param desLocationName The destination location (or point) name.
   * @return A copy of this object, differing in the given destination.
   */
  public DestinationCreationTO withDestLocationName(@Nonnull String desLocationName) {
    return new DestinationCreationTO(destLocationName, destOperation, getName(), getModifiableProperties());
  }

  /**
   * Returns the operation to be performed at the destination.
   *
   * @return The operation to be performed at the destination.
   */
  @Nonnull
  public String getDestOperation() {
    return destOperation;
  }
  
  /**
   * Creates a copy of this object with the given operation to be performed at the destination.
   * 
   * @param destOperation The operation.
   * @return A copy of this object, differing in the given destination operation.
   */
  public DestinationCreationTO withDestOperation(@Nonnull String destOperation) {
    return new DestinationCreationTO(destLocationName, destOperation, getName(), getModifiableProperties());
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/routing/DefaultRouterTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing;

import java.util.HashSet;
import java.util.Set;
import org.junit.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.invocation.InvocationOnMock;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.routing.GroupMapper;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObject;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;

/**
 * Test cases for the {@link DefaultRouter}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultRouterTest {

  /**
   * The vehicles which are returned when asking the kernel for vehicles.
   */
  private final Set<Vehicle> vehicles = new HashSet<>();

  /**
   * The class to test.
   */
  private Router router;

  /**
   * The mocked object service to use.
   */
  private TCSObjectService objectService;

  /**
   * The builder for routing tables.
   */
  private PointRouterFactory builder;

  /**
   * The routing group mapper.
   */
  private GroupMapper routingGroupMapper;

  /**
   * The configuration.
   */
  private DefaultRouterConfiguration configuration;

  @Before
  public void setUp() {
    objectService = mock(TCSObjectService.class);
    builder = mock(PointRouterFactory.class);
    when(objectService.fetchObjects(Vehicle.class)).thenReturn(vehicles);
    when(objectService.fetchObject(eq(Vehicle.class), anyString()))
        .then(o -> vehicles.stream()
        .filter(t -> filterByName(o, t))
        .findFirst().orElse(null));
    routingGroupMapper = new DefaultRoutingGroupMapper();
    configuration = mock(DefaultRouterConfiguration.class);
    when(configuration.routeToCurrentPosition()).thenReturn(false);
    router = spy(createRouter());
  }

  @Test
  public void shouldUseDefaultRoutingGroup() {
    Point sourcePoint = new Point("Some source point");
    Point destinationPoint = new Point("Some destination point");

    router.initialize();
    router.getCosts(createVehicle("Vehicle-000", -1), sourcePoint, destinationPoint);
    router.getCosts(createVehicle("Vehicle-001", -1), sourcePoint, destinationPoint);
    router.getCosts(createVehicle("Vehicle-002", -1), sourcePoint, destinationPoint);

    verify(builder, times(1)).createPointRouter(any());
  }

  @Test
  public void shouldUseDefinedRoutingGroup() {
    Point sourcePoint = new Point("Some source point");
    Point destinationPoint = new Point("Some destination point");

    router.initialize();
    router.getCosts(createVehicle("Vehicle-000", 1), sourcePoint, destinationPoint);
    router.getCosts(createVehicle("Vehicle-001", 1), sourcePoint, destinationPoint);
    router.getCosts(createVehicle("Vehicle-002", 1), sourcePoint, destinationPoint);

    verify(builder, times(1)).createPointRouter(any());
  }

  @Test
  public void shouldUseDefaultAndSetRoutingGroups() {
    Point sourcePoint = new Point("Some source point");
    Point destinationPoint = new Point("Some destination point");

    router.initialize();
    router.getCosts(createVehicle("Vehicle-000", 1), sourcePoint, destinationPoint);
    router.getCosts(createVehicle("Vehicle-001", 1), sourcePoint, destinationPoint);
    router.getCosts(createVehicle("Vehicle-002", -1), sourcePoint, destinationPoint);

    verify(builder, times(2)).createPointRouter(any());
  }

  @Test
  public void shouldUseSetRoutingGroups() {
    Point sourcePoint = new Point("Some source point");
    Point destinationPoint = new Point("Some destination point");

    router.initialize();
    for (int x = 0; x < 15; x++) {
      router.getCosts(createVehicle("Vehicle-0" + x, x), sourcePoint, destinationPoint);
    }

    verify(builder, times(15)).createPointRouter(any());
  }

  /**
   * Creates a vehicle with a unique id, the given name and the given routing group.
   * If the routing group is negative no property will be added.
   * The vehicle will be added to the kernel objects.
   *
   * @param name The name of the vehicle
   * @param routingGroup The routing group of the vehicle
   * @return The vehicle
   */
  private Vehicle createVehicle(String name, int routingGroup) {
    Vehicle vehicle = new Vehicle(name);
    if (routingGroup >= 0) {
      vehicle = vehicle.withProperty(Router.PROPKEY_ROUTING_GROUP, String.valueOf(routingGroup));
    }
    vehicles.add(vehicle);

    return vehicle;
  }

  /**
   * Creates the router with mocked routing table builder to return a new routing table on each
   * request.
   *
   * @return The router
   */
  private Router createRouter() {
    when(builder.createPointRouter(any())).thenReturn(mock(PointRouter.class));

    return new DefaultRouter(objectService, builder, routingGroupMapper, configuration);
  }

  /**
   * Stream filter to check if the second argument of the invocation is equal to the object's name.
   *
   * @param mock The method call on the mock
   * @param object The kernel object to compare if the call wants this object
   * @return <code>true</code> if the objects name is equal to the second invocation argument
   */
  private boolean filterByName(InvocationOnMock mock, TCSObject<?> object) {
    Object arg1 = mock.getArguments()[1];
    //Here one can add different types for the getTCSObject method like TCSObjectReference or
    //TCSResourceReference
    if (arg1 instanceof String) {
      return filterByName((String) arg1, object);
    }
    return false;
  }

  /**
   * Stream filter to check if object has the given name.
   *
   * @param name The object name to check
   * @param object The kernel object to compare with the given name
   * @return <code>true</code> if the objects name is equal to the given name
   */
  private boolean filterByName(String name, TCSObject<?> object) {
    return name.equals(object.getName());
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/ModelAttribute.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.io.Serializable;
import org.opentcs.guing.model.ModelComponent;

/**
 * Interface to specify how an attribute of a model component must appear.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface ModelAttribute
    extends Serializable {

  public static enum ChangeState {

    NOT_CHANGED,
    CHANGED,
    DETAIL_CHANGED,
  };

  /**
   * Returns the model component this attribute is attached to.
   *
   * @return The model component.
   */
  public ModelComponent getModel();

  /**
   * Sets the model component this attribute is attached to.
   *
   * @param model The model component.
   */
  public void setModel(ModelComponent model);

  /**
   * Marks the attribute as changed.
   */
  void markChanged();

  /**
   * Marks the attribute as not changed.
   */
  void unmarkChanged();

  /**
   * Sets the change state for this attribute.
   *
   * @param changeState The new change state.
   */
  void setChangeState(AbstractModelAttribute.ChangeState changeState);

  /**
   * Returns whether or not the attribute has changed.
   *
   * @return {@code true}, if the state of the model attribute has changed, otherwiese
   * {@code false}.
   */
  boolean hasChanged();

  /**
   * Sets the description of the attribute.
   *
   * @param description The description.
   */
  void setDescription(String description);

  /**
   * Returns the description of the attribute.
   *
   * @return The description.
   */
  String getDescription();

  /**
   * Sets the tooltip text for this attribute.
   *
   * @param helptext The tooltip text.
   */
  void setHelptext(String helptext);

  /**
   * Returns the tooltip text for this attribute.
   *
   * @return The helptext.
   */
  String getHelptext();

  /**
   *
   * Sets whether or not the attribute is collectively editable with attributes
   * of the same name of other model components.
   *
   * @param collectiveEditable Whether the attribute is collectively editable with attributes
   * of the same name of other model components.
   */
  void setCollectiveEditable(boolean collectiveEditable);

  /**
   * Returns whether or not the attribute is collectively editable with attributes of the same name
   * of other model components.
   *
   * @return Whether the attribute is collectively editable with attributes of the same name
   * of other model components.
   */
  boolean isCollectiveEditable();

  /**
   * Sets whether or not the attribute can be changed in modelling mode.
   * @param editable True if the attribute can be changed in modelling mode.
   */
  void setModellingEditable(boolean editable);

  /**
   * Returns whether or not the attribute can be changed in modelling mode.
   * @return True if the attribute can be changed in modelling mode.
   */
  boolean isModellingEditable();

  /**
   * Sets whether or not the attribute can be changed in operating mode.
   * @param editable True if the attribute can be changed in operating mode.
   */
  void setOperatingEditable(boolean editable);

  /**
   * Returns whether or not the attribute can be changed in operating mode.
   * @return True if the attribute can be changed in operating mode.
   */
  boolean isOperatingEditable();

  /**
   * @return true, if this attribute should be considered when persisting the model to a file or not.
   */
  default boolean isPersistent() {
    return true;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/VehicleProcessModelTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.management;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Queue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.notification.UserNotification;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;
import org.opentcs.drivers.vehicle.VehicleProcessModel;

/**
 * A serializable representation of a {@link VehicleProcessModel}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleProcessModelTO
    implements Serializable {

  /**
   * The vehicle name to this process model.
   */
  private String vehicleName;
  /**
   * Whether the comm adapter is currently enabled.
   */
  private boolean commAdapterEnabled;
  /**
   * Whether the comm adapter is currently connected to the vehicle.
   */
  private boolean commAdapterConnected;
  /**
   * The name of the vehicle's current position.
   */
  private String vehiclePosition;
  /**
   * User notifications published by the comm adapter.
   */
  private Queue<UserNotification> notifications = new LinkedList<>();
  /**
   * The percise position of the vehicle.
   */
  private Triple precisePosition;
  /**
   * The vehicle's orentation angle.
   */
  private double orientationAngle = Double.NaN;
  /**
   * The vehicle's energy level.
   */
  private int energyLevel;
  /**
   * A list of load handling devices attached to the vehicle.
   */
  private List<LoadHandlingDevice> loadHandlingDevices = new LinkedList<>();
  /**
   * The vehicle's state.
   */
  private Vehicle.State vehicleState = Vehicle.State.UNKNOWN;

  public String getVehicleName() {
    return vehicleName;
  }

  public VehicleProcessModelTO setVehicleName(@Nonnull String vehicleName) {
    this.vehicleName = requireNonNull(vehicleName);
    return this;
  }

  public boolean isCommAdapterEnabled() {
    return commAdapterEnabled;
  }

  public VehicleProcessModelTO setCommAdapterEnabled(boolean commAdapterEnabled) {
    this.commAdapterEnabled = commAdapterEnabled;
    return this;
  }

  public boolean isCommAdapterConnected() {
    return commAdapterConnected;
  }

  public VehicleProcessModelTO setCommAdapterConnected(boolean commAdapterConnected) {
    this.commAdapterConnected = commAdapterConnected;
    return this;
  }

  @Nullable
  public String getVehiclePosition() {
    return vehiclePosition;
  }

  public VehicleProcessModelTO setVehiclePosition(@Nullable String vehiclePosition) {
    this.vehiclePosition = vehiclePosition;
    return this;
  }

  @Nonnull
  public Queue<UserNotification> getNotifications() {
    return notifications;
  }

  public VehicleProcessModelTO setNotifications(@Nonnull Queue<UserNotification> notifications) {
    this.notifications = requireNonNull(notifications, "notifications");
    return this;
  }

  @Nullable
  public Triple getPrecisePosition() {
    return precisePosition;
  }

  public VehicleProcessModelTO setPrecisePosition(@Nullable Triple precisePosition) {
    this.precisePosition = precisePosition;
    return this;
  }

  public double getOrientationAngle() {
    return orientationAngle;
  }

  public VehicleProcessModelTO setOrientationAngle(double orientationAngle) {
    this.orientationAngle = orientationAngle;
    return this;
  }

  public int getEnergyLevel() {
    return energyLevel;
  }

  public VehicleProcessModelTO setEnergyLevel(int energyLevel) {
    this.energyLevel = energyLevel;
    return this;
  }

  @Nonnull
  public List<LoadHandlingDevice> getLoadHandlingDevices() {
    return loadHandlingDevices;
  }

  public VehicleProcessModelTO setLoadHandlingDevices(
      @Nonnull List<LoadHandlingDevice> loadHandlingDevices) {
    this.loadHandlingDevices = requireNonNull(loadHandlingDevices, "loadHandlingDevices");
    return this;
  }

  @Nonnull
  public Vehicle.State getVehicleState() {
    return vehicleState;
  }

  public VehicleProcessModelTO setVehicleState(@Nonnull Vehicle.State state) {
    this.vehicleState = requireNonNull(state, "state");
    return this;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/VisualLayoutCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * A transfer object describing a visual layout in the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VisualLayoutCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * This layout's scale on the X axis (in mm/pixel).
   */
  private double scaleX = 50.0;
  /**
   * This layout's scale on the Y axis (in mm/pixel).
   */
  private double scaleY = 50.0;
  /**
   * This layout's model layout elements.
   */
  @Deprecated
  private List<ModelLayoutElementCreationTO> modelElements = new LinkedList<>();
  /**
   * This layout's shape layout elements.
   */
  @Deprecated
  private List<ShapeLayoutElementCreationTO> shapeElements = new LinkedList<>();
  /**
   * This layout's layers.
   */
  private List<Layer> layers = new LinkedList<>();
  /**
   * The layout's layer groups.
   */
  private List<LayerGroup> layerGroups = new LinkedList<>();

  /**
   * Creates a new instance.
   *
   * @param name The name of this visual layout.
   */
  public VisualLayoutCreationTO(@Nonnull String name) {
    super(name);
  }

  @SuppressWarnings("deprecation")
  private VisualLayoutCreationTO(@Nonnull String name,
                                 @Nonnull Map<String, String> properties,
                                 double scaleX,
                                 double scaleY,
                                 @Nonnull List<ModelLayoutElementCreationTO> modelElements,
                                 @Nonnull List<ShapeLayoutElementCreationTO> shapeElements,
                                 @Nonnull List<Layer> layers,
                                 @Nonnull List<LayerGroup> layerGroups) {
    super(name, properties);
    this.scaleX = scaleX;
    this.scaleY = scaleY;
    this.modelElements = requireNonNull(modelElements, "modelElements");
    this.shapeElements = requireNonNull(shapeElements, "shapeElements");
    this.layers = requireNonNull(layers, "layers");
    this.layerGroups = requireNonNull(layerGroups, "layerGroups");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name the new name of the instance.
   * @return A copy of this object, differing in the given value.
   */
  @Override
  public VisualLayoutCreationTO withName(@Nonnull String name) {
    return new VisualLayoutCreationTO(name,
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given value.
   */
  @Override
  public VisualLayoutCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new VisualLayoutCreationTO(getName(),
                                      properties,
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public VisualLayoutCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new VisualLayoutCreationTO(getName(),
                                      propertiesWith(key, value),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Returns this layout's scale on the X axis (in mm/pixel).
   *
   * @return This layout's scale on the X axis.
   */
  public double getScaleX() {
    return scaleX;
  }

  /**
   * Creates a copy of this object with the layout's scale on the X axis (in mm/pixel).
   *
   * @param scaleX The new scale.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayoutCreationTO withScaleX(double scaleX) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Returns this layout's scale on the Y axis (in mm/pixel).
   *
   * @return This layout's scale on the Y axis.
   */
  public double getScaleY() {
    return scaleY;
  }

  /**
   * Creates a copy of this object with the given layout's scale on the Y axis (in mm/pixel)
   *
   * @param scaleY The new scale.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayoutCreationTO withScaleY(double scaleY) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Returns the model layout elements of this visual layout.
   *
   * @return The model layout elements of this visual layout.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  @Nonnull
  public List<ModelLayoutElementCreationTO> getModelElements() {
    return Collections.unmodifiableList(modelElements);
  }

  /**
   * Creates a copy of this object with the given model elements
   *
   * @param modelElements The new model layout elements.
   * @return A copy of this object, differing in the layout elements of this visual layout.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public VisualLayoutCreationTO withModelElements(
      @Nonnull List<ModelLayoutElementCreationTO> modelElements) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Creates a copy of this object with the given model element.
   *
   * @param modelElement The new model layout elements.
   * @return A copy of this object, differing in the layout elements of this visual layout.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public VisualLayoutCreationTO withModelElement(
      @Nonnull ModelLayoutElementCreationTO modelElement) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      listWithAppendix(modelElements, modelElement),
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Returns the shape layout elements of this visual layout.
   *
   * @return The shape layout elements of this visual layout.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  @Nonnull
  public List<ShapeLayoutElementCreationTO> getShapeElements() {
    return Collections.unmodifiableList(shapeElements);
  }

  /**
   * Creates a copy of this object with the given shape elements.
   *
   * @param shapeElements the new shape layout elements.
   * @return A copy of this object, differing in the shape layout elements of this visual layout.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public VisualLayoutCreationTO withShapeElements(
      @Nonnull List<ShapeLayoutElementCreationTO> shapeElements) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Creates a copy of this object with the given shape element.
   *
   * @param shapeElement the new shape layout element.
   * @return A copy of this object, differing in the shape layout elements of this visual layout.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  public VisualLayoutCreationTO withShapeElement(
      @Nonnull ShapeLayoutElementCreationTO shapeElement) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      listWithAppendix(shapeElements, shapeElement),
                                      layers,
                                      layerGroups);
  }

  /**
   * Returns the layers of this visual layout.
   *
   * @return The layers of this visual layout.
   */
  @Nonnull
  public List<Layer> getLayers() {
    return Collections.unmodifiableList(layers);
  }

  /**
   * Creates a copy of this object, with the given layers.
   *
   * @param layers The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayoutCreationTO withLayers(@Nonnull List<Layer> layers) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Creates a copy of this object, with the given layer.
   *
   * @param layer The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayoutCreationTO withLayer(@Nonnull Layer layer) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      listWithAppendix(layers, layer),
                                      layerGroups);
  }

  /**
   * Returns the layer groups of this visual layout.
   *
   * @return The layer groups of this visual layout.
   */
  @Nonnull
  public List<LayerGroup> getLayerGroups() {
    return Collections.unmodifiableList(layerGroups);
  }

  /**
   * Creates a copy of this object, with the given layer groups.
   *
   * @param layerGroups The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayoutCreationTO withLayerGroups(@Nonnull List<LayerGroup> layerGroups) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      layerGroups);
  }

  /**
   * Creates a copy of this object, with the given layer group.
   *
   * @param layerGroup The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VisualLayoutCreationTO withLayerGroup(@Nonnull LayerGroup layerGroup) {
    return new VisualLayoutCreationTO(getName(),
                                      getModifiableProperties(),
                                      scaleX,
                                      scaleY,
                                      modelElements,
                                      shapeElements,
                                      layers,
                                      listWithAppendix(layerGroups, layerGroup));
  }

  @Override
  public String toString() {
    return "VisualLayoutCreationTO{"
        + "name=" + getName()
        + ", scaleX=" + scaleX
        + ", scaleY=" + scaleY
        + ", modelElements=" + modelElements
        + ", shapeElements=" + shapeElements
        + ", layers=" + layers
        + ", layerGroups=" + layerGroups
        + ", properties=" + getProperties()
        + '}';
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/ObjectHistory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data;

import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A history of events related to an object.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ObjectHistory
    implements Serializable {

  /**
   * The actual history entries.
   */
  private final List<Entry> entries;

  /**
   * Creates a new instance.
   */
  public ObjectHistory() {
    this(new ArrayList<>());
  }

  /**
   * Creates a new instance with the given list of entries.
   *
   * @param entries
   */
  private ObjectHistory(List<Entry> entries) {
    this.entries = Collections.unmodifiableList(requireNonNull(entries, "entries"));
  }

  /**
   * Returns this history's entries.
   *
   * @return This history's entries.
   */
  public List<Entry> getEntries() {
    return entries;
  }

  /**
   * Returns a copy of this object, with the given entries.
   *
   * @param entries The entries.
   * @return A copy of this object, with the given entries.
   */
  public ObjectHistory withEntries(List<Entry> entries) {
    return new ObjectHistory(entries);
  }

  /**
   * Returns a copy of this object, with the given entry appended.
   *
   * @param entry The entry.
   * @return A copy of this object, with the given entry appended.
   */
  public ObjectHistory withEntryAppended(Entry entry) {
    requireNonNull(entry, "entry");

    List<Entry> newEntries = new ArrayList<>(entries.size() + 1);
    newEntries.addAll(entries);
    newEntries.add(entry);
    return new ObjectHistory(newEntries);
  }

  @Override
  public String toString() {
    return "ObjectHistory{" + "entries=" + entries + '}';
  }

  /**
   * An entry/event in a history.
   */
  public static class Entry
      implements Serializable {

    /**
     * The point of time at which the event occured.
     */
    private final Instant timestamp;
    /**
     * A code identifying the event that occured.
     */
    private final String eventCode;
    /**
     * Supplementary information about the event.
     * How this information is to be interpreted (if at all) depends on the respective event code.
     */
    private final Object supplement;

    /**
     * Creates a new instance.
     *
     * @param timestamp The point of time at which the event occured.
     * @param eventCode A code identifying the event that occured.
     * @param supplement Supplementary information about the event.
     * Must be {@link Serializable} and should provide a human-readable default representation from
     * its {@code toString()} method.
     */
    public Entry(Instant timestamp, String eventCode, Object supplement) {
      this.timestamp = requireNonNull(timestamp, "timestamp");
      this.eventCode = requireNonNull(eventCode, "eventCode");
      this.supplement = requireNonNull(supplement, "supplement");
      checkArgument(supplement instanceof Serializable, "supplement is not serializable");
    }

    /**
     * Creates a new instance with an empty supplement.
     *
     * @param timestamp The point of time at which the event occured.
     * @param eventCode A code identifying the event that occured.
     */
    public Entry(Instant timestamp, String eventCode) {
      this(timestamp, eventCode, "");
    }

    /**
     * Creates a new instance with the timestamp set to the current point of time.
     *
     * @param eventCode A code identifying the event that occured.
     * @param supplement Supplementary information about the event.
     * Must be {@link Serializable} and should provide a human-readable default representation from
     * its {@code toString()} method.
     */
    public Entry(String eventCode, Object supplement) {
      this(Instant.now(), eventCode, supplement);
    }

    /**
     * Creates a new instance with the timestamp set to the current point of time and an empty
     * supplement.
     *
     * @param eventCode A code identifying the event that occured.
     */
    public Entry(String eventCode) {
      this(eventCode, "");
    }

    /**
     * Returns this entry's timestamp.
     *
     * @return This entry's timestamp.
     */
    @Nonnull
    public Instant getTimestamp() {
      return timestamp;
    }

    /**
     * Returns this entry's event code.
     *
     * @return This entry's event code.
     */
    @Nonnull
    public String getEventCode() {
      return eventCode;
    }

    /**
     * Returns a supplemental object providing details about the event.
     *
     * @return A supplemental object providing details about the event.
     */
    @Nonnull
    public Object getSupplement() {
      return supplement;
    }

    @Override
    public String toString() {
      return "Entry{"
          + "timestamp=" + timestamp
          + ", eventCode=" + eventCode
          + ", supplement=" + supplement
          + '}';
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/course/DrawingMethod.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.course;

/**
 * An interface for drawing methods. Possible drawing methods are:
 * <p>
 * <ul> <li> symbolic: No relation between the real position and the position of the figure.
 * <li> coordinate based: The position of the figure is the exact real position. </ul>
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface DrawingMethod {

  /**
   * Returns the origin point.
   *
   * @return the origin point.
   */
  Origin getOrigin();
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/CandidateFilterResult.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;

/**
 * The result of an assignment candidate filter operation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateFilterResult {

  private final AssignmentCandidate candidate;

  private final Collection<String> filterReasons;

  public CandidateFilterResult(AssignmentCandidate candidate, Collection<String> filterReasons) {
    this.candidate = requireNonNull(candidate, "candidate");
    this.filterReasons = requireNonNull(filterReasons, "filterReasons");
  }

  public AssignmentCandidate getCandidate() {
    return candidate;
  }

  public Collection<String> getFilterReasons() {
    return filterReasons;
  }

  public boolean isFiltered() {
    return !filterReasons.isEmpty();
  }

  public OrderFilterResult toFilterResult() {
    return new OrderFilterResult(candidate.getTransportOrder(), filterReasons);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/ColorPropertyCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Color;
import java.awt.Frame;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import org.opentcs.guing.components.properties.type.ColorProperty;
import static org.opentcs.guing.util.I18nPlantOverview.PROPERTIES_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * A cell editor for a color property.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class ColorPropertyCellEditor
    extends javax.swing.AbstractCellEditor
    implements javax.swing.table.TableCellEditor,
               java.awt.event.ActionListener {

  /**
   * The button to use for the editor.
   */
  protected JButton fButton;
  /**
   * The color property.
   */
  protected ColorProperty fColorProperty;
  /**
   * The parent table.
   */
  protected JTable fTable;

  /**
   * Creates a new instance of ColorPropertyCellEditor.
   */
  public ColorPropertyCellEditor() {
    super();
    fButton = new JButton();
    fButton.setBorderPainted(false);
    fButton.addActionListener(this);
  }

  @Override
  public java.awt.Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {
    fTable = table;
    fColorProperty = (ColorProperty) value;
    fButton.setBackground(fColorProperty.getColor());
    return fButton;
  }

  @Override
  public Object getCellEditorValue() {
    return fColorProperty;
  }

  @Override
  public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(PROPERTIES_PATH);

    Frame parent = JOptionPane.getFrameForComponent(fTable);
    Color newColor = JColorChooser.showDialog(parent,
                                              bundle.getString("colorPropertyCellEditor.dialog_colorSelection.title"),
                                              fColorProperty.getColor());

    if (newColor != null) {
      Color oldColor = fColorProperty.getColor();
      fColorProperty.setColor(newColor);

      if (newColor != oldColor) {
        fColorProperty.markChanged();
      }
    }

    stopCellEditing();
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/SymbolProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property for a graphical symbol.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class SymbolProperty
    extends AbstractComplexProperty {

  /**
   * The location representation.
   */
  private LocationRepresentation locationRepresentation;

  /**
   * Creates a new instance.
   *
   * @param model The model component this property belongs to.
   */
  public SymbolProperty(ModelComponent model) {
    super(model);
  }

  @Override
  public Object getComparableValue() {
    return locationRepresentation;
  }

  /**
   * Set the location representation for this property.
   *
   * @param locationRepresentation The location representation.
   */
  public void setLocationRepresentation(LocationRepresentation locationRepresentation) {
    this.locationRepresentation = locationRepresentation;
  }

  /**
   * Returns the location representation for this property.
   *
   * @return The location representation.
   */
  public LocationRepresentation getLocationRepresentation() {
    return locationRepresentation;
  }

  @Override // java.lang.Object
  public String toString() {
    if (fValue != null) {
      return fValue.toString();
    }

    return locationRepresentation == null ? "" : locationRepresentation.name();
  }

  @Override // AbstractProperty
  public void copyFrom(Property property) {
    SymbolProperty symbolProperty = (SymbolProperty) property;
    symbolProperty.setValue(null);
    setLocationRepresentation(symbolProperty.getLocationRepresentation());
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/routing/edgeevaluator/EdgeEvaluatorCompositeTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.edgeevaluator;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import org.junit.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.routing.Edge;
import org.opentcs.components.kernel.routing.EdgeEvaluator;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.routing.jgrapht.ShortestPathConfiguration;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EdgeEvaluatorCompositeTest {

  private static final String EVALUATOR_1 = "EVALUATOR_1";
  private static final String EVALUATOR_2 = "EVALUATOR_2";
  private static final String EVALUATOR_3 = "EVALUATOR_3";

  private Edge edge;

  private Vehicle vehicle;

  private ShortestPathConfiguration configuration;
  private final Map<String, EdgeEvaluator> evaluators = new HashMap<>();

  @Before
  public void setUp() {
    Point srcPoint = new Point("srcPoint");
    Point dstPoint = new Point("dstPoint");

    edge = new Edge(new Path("pathName", srcPoint.getReference(), dstPoint.getReference()),
                    true);
    vehicle = new Vehicle("someVehicle");

    configuration = mock(ShortestPathConfiguration.class);

    evaluators.put(EVALUATOR_1, (someEdge, someVehicle) -> 1.0);
    evaluators.put(EVALUATOR_2, (someEdge, someVehicle) -> 0.9);
    evaluators.put(EVALUATOR_3, (someEdge, someVehicle) -> Double.POSITIVE_INFINITY);
  }

  @After
  public void tearDown() {
  }

  @Test
  public void computeZeroWithoutComponents() {
    EdgeEvaluatorComposite edgeEvaluator = new EdgeEvaluatorComposite(configuration, evaluators);

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(0.0));
  }

  @Test
  public void computeSumOfOneComponent() {
    when(configuration.edgeEvaluators()).thenReturn(List.of(EVALUATOR_1));
    EdgeEvaluatorComposite edgeEvaluator = new EdgeEvaluatorComposite(configuration, evaluators);

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(1.0));
  }

  @Test
  public void computeSumOfTwoComponents() {
    when(configuration.edgeEvaluators()).thenReturn(List.of(EVALUATOR_1, EVALUATOR_2));
    EdgeEvaluatorComposite edgeEvaluator = new EdgeEvaluatorComposite(configuration, evaluators);

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(1.9));
  }

  @Test
  public void computeInfinityIfAnyComponentReturnsInfinity() {
    when(configuration.edgeEvaluators()).thenReturn(List.of(EVALUATOR_1, EVALUATOR_2, EVALUATOR_3));
    EdgeEvaluatorComposite edgeEvaluator = new EdgeEvaluatorComposite(configuration, evaluators);

    assertThat(edgeEvaluator.computeWeight(edge, vehicle), is(Double.POSITIVE_INFINITY));
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v002/PointTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v002;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "id", "xPosition", "yPosition", "zPosition",
                      "vehicleOrientationAngle", "type", "outgoingPaths", "properties"})
public class PointTO
    extends PlantModelElementTO {
  
  private Long xPosition = 0L;
  private Long yPosition = 0L;
  private Long zPosition = 0L;
  private Float vehicleOrientationAngle = 0.0F;
  private String type = "";
  private List<OutgoingPath> outgoingPaths = new ArrayList<>();

  @XmlAttribute(required = true)
  public Long getxPosition() {
    return xPosition;
  }

  public PointTO setxPosition(@Nonnull Long xPosition) {
    requireNonNull(xPosition, "xPosition");
    this.xPosition = xPosition;
    return this;
  }

  @XmlAttribute(required = true)
  public Long getyPosition() {
    return yPosition;
  }

  public PointTO setyPosition(@Nonnull Long yPosition) {
    requireNonNull(yPosition, "yPosition");
    this.yPosition = yPosition;
    return this;
  }

  @XmlAttribute
  public Long getzPosition() {
    return zPosition;
  }

  public PointTO setzPosition(@Nonnull Long zPosition) {
    requireNonNull(zPosition, "zPosition");
    this.zPosition = zPosition;
    return this;
  }

  @XmlAttribute
  public Float getVehicleOrientationAngle() {
    return vehicleOrientationAngle;
  }

  public PointTO setVehicleOrientationAngle(@Nonnull Float vehicleOrientationAngle) {
    requireNonNull(vehicleOrientationAngle, "vehicleOrientationAngle");
    this.vehicleOrientationAngle = vehicleOrientationAngle;
    return this;
  }

  @XmlAttribute(required = true)
  public String getType() {
    return type;
  }

  public PointTO setType(@Nonnull String type) {
    requireNonNull(type, "type");
    this.type = type;
    return this;
  }

  @XmlElement(name = "outgoingPath")
  public List<OutgoingPath> getOutgoingPaths() {
    return outgoingPaths;
  }

  public PointTO setOutgoingPaths(@Nonnull List<OutgoingPath> outgoingPath) {
    requireNonNull(outgoingPath, "outgoingPath");
    this.outgoingPaths = outgoingPath;
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  public static class OutgoingPath {

    private String name = "";

    @XmlAttribute(required = true)
    public String getName() {
      return name;
    }

    public OutgoingPath setName(@Nonnull String name) {
      requireNonNull(name, "name");
      this.name = name;
      return this;
    }
  }
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/kernel/peripherals/PeripheralAttachmentManagerTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import org.junit.*;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import org.opentcs.common.peripherals.NullPeripheralCommAdapterDescription;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
import org.opentcs.kernel.KernelApplicationConfiguration;
import org.opentcs.util.ExplainedBoolean;
import org.opentcs.util.event.EventHandler;

/**
 * Tests for the {@link PeripheralAttachmentManager}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralAttachmentManagerTest {

  private static final String LOCATION_NAME = "Location-01";

  private final PeripheralAttachmentManager attachmentManager;
  private final InternalPeripheralService peripheralService;
  private final PeripheralCommAdapterRegistry commAdapterRegistry;
  private final PeripheralCommAdapterFactory commAdapterFactory;
  private final PeripheralEntryPool peripheralEntryPool;

  private final Location location;

  public PeripheralAttachmentManagerTest() {
    peripheralService = mock(InternalPeripheralService.class);
    commAdapterRegistry = mock(PeripheralCommAdapterRegistry.class);
    commAdapterFactory = mock(PeripheralCommAdapterFactory.class);
    peripheralEntryPool = new PeripheralEntryPool(peripheralService);
    attachmentManager = spy(new PeripheralAttachmentManager(peripheralService,
                                                            mock(LocalPeripheralControllerPool.class),
                                                            commAdapterRegistry,
                                                            peripheralEntryPool,
                                                            mock(EventHandler.class),
                                                            mock(KernelApplicationConfiguration.class)));

    location = createLocation(LOCATION_NAME);
  }

  @Before
  public void setUp() {
    Set<Location> locations = new HashSet<>();
    locations.add(location);
    when(peripheralService.fetchObjects(Location.class)).thenReturn(locations);
    when(peripheralService.fetchObject(any(), eq(location.getReference()))).thenReturn(location);
  }

  @After
  public void tearDown() {
  }

  @Test
  public void shouldHaveInitializedPeripheralEntryPool() {
    attachmentManager.initialize();

    assertThat(peripheralEntryPool.getEntries().size(), is(1));
    assertThat(peripheralEntryPool.getEntryFor(location.getReference()).getCommAdapter(),
               is(instanceOf(NullPeripheralCommAdapter.class)));
  }

  @Test
  public void shouldAttachAdapterToLocation() {
    PeripheralCommAdapter commAdapter = new SimpleCommAdapter(location);
    PeripheralCommAdapterDescription description = new SimpleCommAdapterDescription();
    when(commAdapterRegistry.findFactoryFor(description)).thenReturn(commAdapterFactory);
    when(commAdapterFactory.getAdapterFor(location)).thenReturn(commAdapter);
    when(commAdapterFactory.getDescription()).thenReturn(description);

    attachmentManager.initialize();
    attachmentManager.attachAdapterToLocation(location.getReference(), description);

    assertNotNull(peripheralEntryPool.getEntryFor(location.getReference()));
    assertThat(peripheralEntryPool.getEntryFor(location.getReference()).getCommAdapter(),
               is(commAdapter));
    assertThat(peripheralEntryPool.getEntryFor(location.getReference()).getCommAdapterFactory(),
               is(commAdapterFactory));
  }

  @Test
  public void shouldAutoAttachAdapterToLocation() {
    PeripheralCommAdapterFactory factory = new SimpleCommAdapterFactory();
    when(commAdapterRegistry.findFactoriesFor(location)).thenReturn(Arrays.asList(factory));

    attachmentManager.initialize();

    assertNotNull(peripheralEntryPool.getEntryFor(location.getReference()));
    assertThat(peripheralEntryPool.getEntryFor(location.getReference()).getCommAdapter(),
               is(instanceOf(SimpleCommAdapter.class)));
    assertThat(peripheralEntryPool.getEntryFor(location.getReference()).getCommAdapterFactory(),
               is(factory));
  }

  @Test
  public void shouldGetAttachmentInformation() {
    attachmentManager.initialize();
    PeripheralAttachmentInformation result
        = attachmentManager.getAttachmentInformation(location.getReference());

    assertThat(result.getLocationReference(), is(location.getReference()));
    assertThat(result.getAttachedCommAdapter(),
               is(instanceOf(NullPeripheralCommAdapterDescription.class)));
  }

  private Location createLocation(String locationName) {
    LocationType locationType = new LocationType("LocationType-01");
    return new Location(locationName, locationType.getReference());
  }

  private class SimpleCommAdapter
      implements PeripheralCommAdapter {

    private final PeripheralProcessModel processModel;

    public SimpleCommAdapter(Location location) {
      this.processModel = new PeripheralProcessModel(location.getReference());
    }

    @Override
    public void initialize() {
    }

    @Override
    public boolean isInitialized() {
      return true;
    }

    @Override
    public void terminate() {
    }

    @Override
    public void enable() {
    }

    @Override
    public void disable() {
    }

    @Override
    public boolean isEnabled() {
      return false;
    }

    @Override
    public PeripheralProcessModel getProcessModel() {
      return processModel;
    }

    @Override
    public ExplainedBoolean canProcess(PeripheralJob job) {
      return new ExplainedBoolean(true, "");
    }

    @Override
    public void process(PeripheralJob job, PeripheralJobCallback callback) {
    }

    @Override
    public void execute(PeripheralAdapterCommand command) {
    }
  }

  private class SimpleCommAdapterFactory
      implements PeripheralCommAdapterFactory {

    @Override
    public void initialize() {
    }

    @Override
    public boolean isInitialized() {
      return true;
    }

    @Override
    public void terminate() {
    }

    @Override
    public PeripheralCommAdapterDescription getDescription() {
      return new SimpleCommAdapterDescription();
    }

    @Override
    public boolean providesAdapterFor(Location location) {
      return true;
    }

    @Override
    public PeripheralCommAdapter getAdapterFor(Location location) {
      return new SimpleCommAdapter(location);
    }

  }

  private class SimpleCommAdapterDescription
      extends PeripheralCommAdapterDescription {

    @Override
    public String getDescription() {
      return getClass().getName();
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/ObjectExistsException.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data;

import org.opentcs.access.KernelRuntimeException;

/**
 * Thrown when an object was supposed to be created or renamed, but another
 * object with the same ID/name/attributes already exists.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ObjectExistsException
    extends KernelRuntimeException {

  /**
   * Creates a new ObjectExistsException with the given detail message.
   *
   * @param message The detail message.
   */
  public ObjectExistsException(String message) {
    super(message);
  }

  /**
   * Creates a new ObjectExistsException with the given detail message and
   * cause.
   *
   * @param message The detail message.
   * @param cause The cause.
   */
  public ObjectExistsException(String message, Throwable cause) {
    super(message, cause);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/workingset/TransportOrderPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.workingset;

import java.time.Instant;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.opentcs.access.to.order.DestinationCreationTO;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.ObjectNameProvider;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import static org.opentcs.util.Assertions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A {@code TransportOrderPool} keeps all {@code TransportOrder}s for an openTCS
 * kernel and provides methods to create and manipulate them.
 * <p>
 * Note that no synchronization is done inside this class. Concurrent access of
 * instances of this class must be synchronized externally.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderPool {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(TransportOrderPool.class);
  /**
   * The system's global object pool.
   */
  private final TCSObjectPool objectPool;
  /**
   * Provides names for transport orders and order sequences.
   */
  private final ObjectNameProvider objectNameProvider;

  /**
   * Creates a new instance.
   *
   * @param objectPool The object pool serving as the container for this order pool's data.
   * @param orderNameProvider Provides names for transport orders.
   */
  @Inject
  public TransportOrderPool(TCSObjectPool objectPool,
                            ObjectNameProvider orderNameProvider) {
    this.objectPool = requireNonNull(objectPool, "objectPool");
    this.objectNameProvider = requireNonNull(orderNameProvider, "orderNameProvider");
  }

  /**
   * Returns the <code>TCSObjectPool</code> serving as the container for this
   * order pool's data.
   *
   * @return The <code>TCSObjectPool</code> serving as the container for this
   * order pool's data.
   */
  public TCSObjectPool getObjectPool() {
    LOG.debug("method entry");
    return objectPool;
  }

  /**
   * Removes all transport orders from this pool.
   */
  public void clear() {
    LOG.debug("method entry");
    for (TCSObject<?> curObject : objectPool.getObjects((Pattern) null)) {
      if (curObject instanceof TransportOrder
          || curObject instanceof OrderSequence) {
        objectPool.removeObject(curObject.getReference());
        objectPool.emitObjectEvent(null,
                                   curObject,
                                   TCSObjectEvent.Type.OBJECT_REMOVED);
      }
    }
  }

  /**
   * Adds a new transport order to the pool.
   * This method implicitly adds the transport order to its wrapping sequence, if any.
   *
   * @param to The transfer object from which to create the new transport order.
   * @return The newly created transport order.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   * @throws IllegalArgumentException If the order is supposed to be part of an order sequence, but
   * the sequence is already complete, the categories of the two differ or the intended vehicles of
   * the two differ.
   */
  public TransportOrder createTransportOrder(TransportOrderCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, IllegalArgumentException {
    TransportOrder newOrder = new TransportOrder(nameFor(to),
                                                 toDriveOrders(to.getDestinations()))
        .withCreationTime(Instant.now())
        .withPeripheralReservationToken(to.getPeripheralReservationToken())
        .withIntendedVehicle(toVehicleReference(to.getIntendedVehicleName()))
        .withType(to.getType())
        .withDeadline(to.getDeadline())
        .withDispensable(to.isDispensable())
        .withWrappingSequence(getWrappingSequence(to))
        .withDependencies(getDependencies(to))
        .withProperties(to.getProperties());
    objectPool.addObject(newOrder);
    objectPool.emitObjectEvent(newOrder, null, TCSObjectEvent.Type.OBJECT_CREATED);

    if (newOrder.getWrappingSequence() != null) {
      OrderSequence sequence = objectPool.getObject(OrderSequence.class,
                                                    newOrder.getWrappingSequence());
      OrderSequence prevSeq = sequence;
      sequence = objectPool.replaceObject(sequence.withOrder(newOrder.getReference()));
      objectPool.emitObjectEvent(sequence, prevSeq, TCSObjectEvent.Type.OBJECT_MODIFIED);
    }

    // Return the newly created transport order.
    return newOrder;
  }

  /**
   * Sets a transport order's state.
   *
   * @param ref A reference to the transport order to be modified.
   * @param newState The transport order's new state.
   * @return The modified transport order.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public TransportOrder setTransportOrderState(TCSObjectReference<TransportOrder> ref,
                                               TransportOrder.State newState)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    TransportOrder order = objectPool.getObject(TransportOrder.class, ref);
    TransportOrder previousState = order;
    order = objectPool.replaceObject(order.withState(newState));
    objectPool.emitObjectEvent(order,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return order;
  }

  /**
   * Sets a transport order's processing vehicle.
   *
   * @param orderRef A reference to the transport order to be modified.
   * @param vehicleRef A reference to the vehicle processing the order.
   * @param driveOrders The drive orders containing the data to be copied into this transport
   * order's drive orders.
   * @return The modified transport order.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   * @throws IllegalArgumentException If the destinations of the given drive
   * orders do not match the destinations of the drive orders in this transport
   * order.
   */
  public TransportOrder setTransportOrderProcessingVehicle(
      TCSObjectReference<TransportOrder> orderRef,
      TCSObjectReference<Vehicle> vehicleRef,
      List<DriveOrder> driveOrders)
      throws ObjectUnknownException, IllegalArgumentException {
    TransportOrder order = objectPool.getObject(TransportOrder.class, orderRef);
    TransportOrder previousState = order;
    if (vehicleRef == null) {
      order = objectPool.replaceObject(order.withProcessingVehicle(null));
    }
    else {
      Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
      order = objectPool.replaceObject(
          order.withProcessingVehicle(vehicle.getReference())
              .withDriveOrders(driveOrders)
              .withCurrentDriveOrderIndex(0)
      );
      if (order.getCurrentDriveOrder() != null) {
        order = objectPool.replaceObject(
            order.withCurrentDriveOrderState(DriveOrder.State.TRAVELLING));
      }
    }
    objectPool.emitObjectEvent(order,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return order;
  }

  /**
   * Copies drive order data from a list of drive orders to the given transport
   * order's future drive orders.
   *
   * @param orderRef A reference to the transport order to be modified.
   * @param newOrders The drive orders containing the data to be copied into
   * this transport order's drive orders.
   * @return The modified transport order.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   * @throws IllegalArgumentException If the destinations of the given drive
   * orders do not match the destinations of the drive orders in this transport
   * order.
   */
  public TransportOrder setTransportOrderDriveOrders(TCSObjectReference<TransportOrder> orderRef,
                                                     List<DriveOrder> newOrders)
      throws ObjectUnknownException, IllegalArgumentException {
    LOG.debug("method entry");
    TransportOrder order = objectPool.getObject(TransportOrder.class, orderRef);
    TransportOrder previousState = order;
    order = objectPool.replaceObject(order.withDriveOrders(newOrders));
    objectPool.emitObjectEvent(order,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return order;
  }

  /**
   * Updates a transport order's current drive order.
   * Marks the current drive order as finished, adds it to the list of past
   * drive orders and sets the current drive order to the next one of the list
   * of future drive orders (or <code>null</code>, if that list is empty).
   * If the current drive order is <code>null</code> because all drive orders
   * have been finished already or none has been started, yet, nothing happens.
   *
   * @param ref A reference to the transport order to be modified.
   * @return The modified transport order.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public TransportOrder setTransportOrderNextDriveOrder(TCSObjectReference<TransportOrder> ref)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    TransportOrder order = objectPool.getObject(TransportOrder.class, ref);
    TransportOrder previousState = order;
    // First, mark the current drive order as FINISHED and send an event.
    // Then, shift drive orders and send a second event.
    // Then, mark the current drive order as TRAVELLING and send another event.
    if (order.getCurrentDriveOrder() != null) {
      order = objectPool.replaceObject(order.withCurrentDriveOrderState(DriveOrder.State.FINISHED));
      TransportOrder newState = order;
      objectPool.emitObjectEvent(newState,
                                 previousState,
                                 TCSObjectEvent.Type.OBJECT_MODIFIED);
      previousState = newState;
      order = objectPool.replaceObject(
          order.withCurrentDriveOrderIndex(order.getCurrentDriveOrderIndex() + 1));
      newState = order;
      objectPool.emitObjectEvent(newState,
                                 previousState,
                                 TCSObjectEvent.Type.OBJECT_MODIFIED);
      previousState = newState;
      if (order.getCurrentDriveOrder() != null) {
        order = objectPool.replaceObject(
            order.withCurrentDriveOrderState(DriveOrder.State.TRAVELLING));
        newState = order;
        objectPool.emitObjectEvent(newState,
                                   previousState,
                                   TCSObjectEvent.Type.OBJECT_MODIFIED);
        previousState = newState;
      }
    }
    objectPool.emitObjectEvent(order,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return order;
  }

  /**
   * Removes the referenced transport order from this pool.
   *
   * @param ref A reference to the transport order to be removed.
   * @return The removed transport order.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public TransportOrder removeTransportOrder(TCSObjectReference<TransportOrder> ref)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    TransportOrder order = objectPool.getObject(TransportOrder.class, ref);
    // Make sure orders currently being processed are not removed.
    checkArgument(!order.hasState(TransportOrder.State.BEING_PROCESSED),
                  "Transport order %s is being processed.",
                  order.getName());
    objectPool.removeObject(ref);
    objectPool.emitObjectEvent(null,
                               order,
                               TCSObjectEvent.Type.OBJECT_REMOVED);
    return order;
  }

  /**
   * Adds a new order sequence to the pool.
   *
   * @param to The transfer object from which to create the new order sequence.
   * @return The newly created order sequence.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  public OrderSequence createOrderSequence(OrderSequenceCreationTO to)
      throws ObjectExistsException, ObjectUnknownException {
    OrderSequence newSequence = new OrderSequence(nameFor(to))
        .withType(to.getType())
        .withIntendedVehicle(toVehicleReference(to.getIntendedVehicleName()))
        .withFailureFatal(to.isFailureFatal())
        .withProperties(to.getProperties());
    objectPool.addObject(newSequence);
    objectPool.emitObjectEvent(newSequence,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);
    // Return the newly created transport order.
    return newSequence;
  }

  /**
   * Sets an order sequence's finished index.
   *
   * @param seqRef A reference to the order sequence to be modified.
   * @param index The sequence's new finished index.
   * @return The modified order sequence.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public OrderSequence setOrderSequenceFinishedIndex(TCSObjectReference<OrderSequence> seqRef,
                                                     int index)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    OrderSequence sequence = objectPool.getObject(OrderSequence.class, seqRef);
    OrderSequence previousState = sequence;
    sequence = objectPool.replaceObject(sequence.withFinishedIndex(index));
    objectPool.emitObjectEvent(sequence,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return sequence;
  }

  /**
   * Sets an order sequence's complete flag.
   *
   * @param seqRef A reference to the order sequence to be modified.
   * @return The modified order sequence.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public OrderSequence setOrderSequenceComplete(
      TCSObjectReference<OrderSequence> seqRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    OrderSequence sequence = objectPool.getObject(OrderSequence.class, seqRef);
    OrderSequence previousState = sequence;
    sequence = objectPool.replaceObject(sequence.withComplete(true));
    objectPool.emitObjectEvent(sequence,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return sequence;
  }

  /**
   * Sets an order sequence's finished flag.
   *
   * @param seqRef A reference to the order sequence to be modified.
   * @return The modified order sequence.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public OrderSequence setOrderSequenceFinished(TCSObjectReference<OrderSequence> seqRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    OrderSequence sequence = objectPool.getObject(OrderSequence.class, seqRef);
    OrderSequence previousState = sequence;
    sequence = objectPool.replaceObject(sequence.withFinished(true));
    objectPool.emitObjectEvent(sequence,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return sequence;
  }

  /**
   * Sets an order sequence's processing vehicle.
   *
   * @param seqRef A reference to the order sequence to be modified.
   * @param vehicleRef A reference to the vehicle processing the order sequence.
   * @return The modified order sequence.
   * @throws ObjectUnknownException If the referenced transport order is not
   * in this pool.
   */
  public OrderSequence setOrderSequenceProcessingVehicle(
      TCSObjectReference<OrderSequence> seqRef,
      TCSObjectReference<Vehicle> vehicleRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    OrderSequence sequence = objectPool.getObject(OrderSequence.class, seqRef);
    OrderSequence previousState = sequence;
    if (vehicleRef == null) {
      sequence = objectPool.replaceObject(sequence.withProcessingVehicle(null));
    }
    else {
      Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
      sequence = objectPool.replaceObject(sequence.withProcessingVehicle(vehicle.getReference()));
    }
    objectPool.emitObjectEvent(sequence,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return sequence;
  }

  /**
   * Removes the referenced order sequence from this pool.
   *
   * @param ref A reference to the order sequence to be removed.
   * @return The removed order sequence.
   * @throws ObjectUnknownException If the referenced order sequence is not in this pool.
   */
  public OrderSequence removeOrderSequence(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    OrderSequence sequence = objectPool.getObject(OrderSequence.class, ref);
    OrderSequence previousState = sequence;
    // XXX Any sanity checks here?
    objectPool.removeObject(ref);
    objectPool.emitObjectEvent(null,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_REMOVED);
    return sequence;
  }

  /**
   * Removes a completed order sequence including its transport orders.
   *
   * @param ref A reference to the order sequence.
   * @throws ObjectUnknownException If the referenced order sequence is not in this pool.
   * @throws IllegalArgumentException If the order sequence is not finished, yet.
   */
  public void removeFinishedOrderSequenceAndOrders(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException, IllegalArgumentException {
    OrderSequence sequence = objectPool.getObject(OrderSequence.class, ref);
    checkArgument(sequence.isFinished(), "Order sequence %s is not finished", sequence.getName());
    OrderSequence previousState = sequence;
    objectPool.removeObject(ref);
    objectPool.emitObjectEvent(null, previousState, TCSObjectEvent.Type.OBJECT_REMOVED);
    // Also remove all orders in the sequence.
    for (TCSObjectReference<TransportOrder> orderRef : sequence.getOrders()) {
      removeTransportOrder(orderRef);
    }
  }

  private Set<TCSObjectReference<TransportOrder>> getDependencies(TransportOrderCreationTO to)
      throws ObjectUnknownException {
    Set<TCSObjectReference<TransportOrder>> result = new HashSet<>();
    for (String dependencyName : to.getDependencyNames()) {
      TransportOrder dep = getObjectPool().getObject(TransportOrder.class, dependencyName);
      if (dep == null) {
        throw new ObjectUnknownException(dependencyName);
      }
      result.add(dep.getReference());
    }
    return result;
  }

  @SuppressWarnings("deprecation")
  private TCSObjectReference<OrderSequence> getWrappingSequence(TransportOrderCreationTO to)
      throws ObjectUnknownException, IllegalArgumentException {
    if (to.getWrappingSequence() == null) {
      return null;
    }
    OrderSequence sequence = getObjectPool().getObject(OrderSequence.class,
                                                       to.getWrappingSequence());
    if (sequence == null) {
      throw new ObjectUnknownException(to.getWrappingSequence());
    }
    checkArgument(!sequence.isComplete(), "Order sequence %s is already complete", sequence);
    checkArgument(Objects.equals(to.getType(), sequence.getType()),
                  "Order sequence %s has different type than order %s: %s != %s",
                  sequence,
                  to.getName(),
                  sequence.getType(),
                  to.getType());
    checkArgument(Objects.equals(to.getIntendedVehicleName(), getIntendedVehicleName(sequence)),
                  "Order sequence %s has different intended vehicle than order %s: %s != %s",
                  sequence,
                  to.getName(),
                  sequence.getIntendedVehicle(),
                  to.getIntendedVehicleName());
    return sequence.getReference();
  }

  private TCSObjectReference<Vehicle> toVehicleReference(String vehicleName)
      throws ObjectUnknownException {
    if (vehicleName == null) {
      return null;
    }
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleName);
    return vehicle.getReference();
  }

  private List<DriveOrder> toDriveOrders(List<DestinationCreationTO> dests)
      throws ObjectUnknownException {
    List<DriveOrder> result = new LinkedList<>();
    for (DestinationCreationTO destTo : dests) {
      TCSObject<?> destObject = objectPool.getObjectOrNull(destTo.getDestLocationName());
      if (!(destObject instanceof Location || destObject instanceof Point)) {
        throw new ObjectUnknownException(destTo.getDestLocationName());
      }
      result.add(new DriveOrder(new DriveOrder.Destination(destObject.getReference())
          .withOperation(destTo.getDestOperation())
          .withProperties(destTo.getProperties())));
    }
    return result;
  }

  @Nullable
  private String getIntendedVehicleName(OrderSequence sequence) {
    return sequence.getIntendedVehicle() == null ? null : sequence.getIntendedVehicle().getName();
  }

  @Nonnull
  private String nameFor(@Nonnull TransportOrderCreationTO to) {
    if (to.hasIncompleteName()) {
      return objectNameProvider.apply(to);
    }
    else {
      return to.getName();
    }
  }

  @Nonnull
  private String nameFor(@Nonnull OrderSequenceCreationTO to) {
    if (to.hasIncompleteName()) {
      return objectNameProvider.apply(to);
    }
    else {
      return to.getName();
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/event/SimpleEventBus.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.event;

import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A plain implementation of {@link EventBus}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SimpleEventBus
    implements EventBus {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(SimpleEventBus.class);
  /**
   * The listeners.
   */
  private final Set<EventHandler> listeners = new CopyOnWriteArraySet<>();

  @Override
  public void onEvent(Object event) {
    try {
      for (EventHandler listener : listeners) {
        listener.onEvent(event);
      }
    }
    catch (Exception exc) {
      LOG.warn("Exception thrown by event handler", exc);
    }
  }

  @Override
  public void subscribe(EventHandler listener) {
    requireNonNull(listener, "listener");

    listeners.add(listener);
  }

  @Override
  public void unsubscribe(EventHandler listener) {
    requireNonNull(listener, "listener");

    listeners.remove(listener);
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/KeyValuePropertyEditorPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import com.google.inject.Inject;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.opentcs.components.plantoverview.PropertySuggestions;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.components.properties.type.MergedPropertySuggestions;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.gui.BoundsPopupMenuListener;

/**
 * A panel for editing a property (key-value pair).
 *
 * @see KeyValueProperty
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class KeyValuePropertyEditorPanel
    extends JPanel
    implements DetailsDialogContent {

  /**
   * The property to be edited.
   */
  private KeyValueProperty fProperty;
  /**
   * The combo box's key textfield.
   */
  private final JTextField keyTextField;
  /**
   * The combo box's value textfield.
   */
  private final JTextField valueTextField;
  /**
   * Suggestions for property keys and values.
   */
  private final PropertySuggestions propertySuggestions;

  /**
   * Creates new instance.
   *
   * @param propertySuggestions The properties that are suggested.
   */
  @Inject
  public KeyValuePropertyEditorPanel(MergedPropertySuggestions propertySuggestions) {
    this.propertySuggestions = requireNonNull(propertySuggestions, "propertySuggestions");
    initComponents();
    valueComboBox.addPopupMenuListener(new BoundsPopupMenuListener());
    keyComboBox.addPopupMenuListener(new BoundsPopupMenuListener());
    fProperty = new KeyValueProperty(null, "", "");
    keyTextField = (JTextField) (keyComboBox.getEditor().getEditorComponent());
    valueTextField = (JTextField) (valueComboBox.getEditor().getEditorComponent());
  }

  @Override
  public void setProperty(Property property) {
    fProperty = (KeyValueProperty) property;
    keyTextField.setText(fProperty.getKey());
    valueTextField.setText(fProperty.getValue());
  }

  @Override
  public void updateValues() {
    fProperty.setKeyAndValue(keyTextField.getText(), valueTextField.getText());
  }

  @Override
  public String getTitle() {
    return ResourceBundleUtil.getBundle(I18nPlantOverview.PROPERTIES_PATH).getString("keyValuePropertyEditorPanel.title");
  }

  @Override
  public Property getProperty() {
    return fProperty;
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    keyLabel = new javax.swing.JLabel();
    valueLabel = new javax.swing.JLabel();
    keyComboBox = new JComboBox<>(propertySuggestions.getKeySuggestions().toArray(new String[propertySuggestions.getKeySuggestions().size()]));
    valueComboBox = new JComboBox<>(propertySuggestions.getValueSuggestions().toArray(new String[propertySuggestions.getValueSuggestions().size()]));

    setLayout(new java.awt.GridBagLayout());

    keyLabel.setFont(keyLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/panels/propertyEditing"); // NOI18N
    keyLabel.setText(bundle.getString("keyValuePropertyEditorPanel.label_key.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(keyLabel, gridBagConstraints);

    valueLabel.setFont(valueLabel.getFont());
    valueLabel.setText(bundle.getString("keyValuePropertyEditorPanel.label_value.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0);
    add(valueLabel, gridBagConstraints);

    keyComboBox.setEditable(true);
    keyComboBox.setPrototypeDisplayValue("tenletters");
    keyComboBox.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        keyValueChangedListener(evt);
      }
    });
    add(keyComboBox, new java.awt.GridBagConstraints());

    valueComboBox.setEditable(true);
    valueComboBox.setPrototypeDisplayValue("tenletters");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    add(valueComboBox, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents

  private void keyValueChangedListener(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_keyValueChangedListener

    Set<String> specSuggestions = propertySuggestions.getValueSuggestionsFor(
        String.valueOf(keyComboBox.getSelectedItem()));
    if (specSuggestions.isEmpty()) {
      specSuggestions = propertySuggestions.getValueSuggestions();
    }
    String[] valueSuggestions = specSuggestions
        .toArray(new String[specSuggestions.size()]);
    Object currentSuggestion = valueComboBox.getEditor().getItem();
    valueComboBox.setModel(new DefaultComboBoxModel<>(valueSuggestions));
    valueComboBox.validate();
    valueComboBox.getEditor().setItem(currentSuggestion);
  }//GEN-LAST:event_keyValueChangedListener

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<String> keyComboBox;
  private javax.swing.JLabel keyLabel;
  private javax.swing.JComboBox<String> valueComboBox;
  private javax.swing.JLabel valueLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/kernel/persistence/XMLFileModelPersisterTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.persistence;

import java.io.File;
import java.io.IOException;
import org.junit.*;
import static org.junit.Assert.assertEquals;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mockito;
import static org.mockito.Mockito.mock;
import org.opentcs.TestEnvironment;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.model.PointCreationTO;
import org.opentcs.access.to.model.VehicleCreationTO;
import org.opentcs.util.persistence.ModelParser;

/**
 * Tests the {@link XMLFileModelPersister}.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class XMLFileModelPersisterTest {

  /**
   * The name of the test model.
   */
  private static final String MODEL_NAME = "Testmodel";

  /**
   * Reads and writes the model.
   */
  private ModelParser modelParser;

  /**
   * The persister instance for testing.
   */
  private XMLFileModelPersister persister;

  /**
   * Captures the first argument when the method writeModelMethod of the modelParser is called.
   */
  @Captor
  private ArgumentCaptor<PlantModelCreationTO> modelCaptor;
  /**
   * Captures the second argument when the method writeModelMethod of the modelParser is called.
   */

  @Captor
  private ArgumentCaptor<File> fileCaptor;

  @Before
  public void setUp()
      throws IOException {
    modelParser = mock(ModelParser.class);
    persister = new XMLFileModelPersister(TestEnvironment.getKernelHomeDirectory(),
                                          modelParser);
    modelCaptor = ArgumentCaptor.forClass(PlantModelCreationTO.class);
    fileCaptor = ArgumentCaptor.forClass(File.class);
  }

  @Test
  public void createXmlFileInGivenDirectory()
      throws IOException {
    persister.saveModel(createTestModel(MODEL_NAME));

    Mockito.verify(modelParser).writeModel(modelCaptor.capture(), fileCaptor.capture());

    assertEquals(TestEnvironment.getKernelHomeDirectory(),
                 fileCaptor.getValue().getParentFile().getParentFile());
    assertEquals(".xml", getFileExtension(fileCaptor.getValue()));
  }

  private PlantModelCreationTO createTestModel(String name) {
    return new PlantModelCreationTO(name)
        .withPoint(new PointCreationTO("testPointName"))
        .withVehicle(new VehicleCreationTO("testVehicleName"));
  }

  private String getFileExtension(File file) {
    return file.getName().substring(file.getName().lastIndexOf("."));
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/DisabledCheckBoxCellRenderer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.awt.Color;
import java.awt.Component;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellRenderer;

/**
 * A table cell renderer for a disabled check box.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class DisabledCheckBoxCellRenderer
    implements TableCellRenderer {

  private final JCheckBox checkBox;

  public DisabledCheckBoxCellRenderer() {
    checkBox = new JCheckBox();
    checkBox.setHorizontalAlignment(SwingConstants.CENTER);
  }

  @Override
  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                 boolean hasFocus, int row, int column) {
    Color bg = isSelected ? table.getSelectionBackground() : table.getBackground();
    checkBox.setBackground(bg);
    checkBox.setEnabled(false);
    checkBox.setSelected(value == Boolean.TRUE);
    return checkBox;
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-ResourceAllocation/src/guiceConfig/java/org/opentcs/guing/plugins/panels/allocation/AllocationPanelModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.allocation;

import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Configures the resource allocation panel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AllocationPanelModule
    extends PlantOverviewInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AllocationPanelModule.class);

  @Override
  protected void configure() {
    ResourceAllocationPanelConfiguration configuration
        = getConfigBindingProvider().get(ResourceAllocationPanelConfiguration.PREFIX,
                                         ResourceAllocationPanelConfiguration.class);

    if (!configuration.enable()) {
      LOG.info("Resource allocation panel disabled by configuration.");
      return;
    }

    pluggablePanelFactoryBinder().addBinding().to(ResourceAllocationPanelFactory.class);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/configuration/package-info.java<|end_filename|>
/**
 * Configuration-related interfaces and annotations.
 */
package org.opentcs.configuration;


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/PathTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name",
                      "sourcePoint",
                      "destinationPoint",
                      "length",
                      "maxVelocity",
                      "maxReverseVelocity",
                      "peripheralOperations",
                      "locked",
                      "properties",
                      "pathLayout"})
public class PathTO
    extends PlantModelElementTO {

  private String sourcePoint = "";
  private String destinationPoint = "";
  private Long length = 0L;
  private Long maxVelocity = 0L;
  private Long maxReverseVelocity = 0L;
  private List<PeripheralOperationTO> peripheralOperations = new ArrayList<>();
  private Boolean locked = false;
  private PathLayout pathLayout = new PathLayout();

  @XmlAttribute(required = true)
  public String getSourcePoint() {
    return sourcePoint;
  }

  public PathTO setSourcePoint(@Nonnull String sourcePoint) {
    requireNonNull(sourcePoint, "sourcePoint");
    this.sourcePoint = sourcePoint;
    return this;
  }

  @XmlAttribute(required = true)
  public String getDestinationPoint() {
    return destinationPoint;
  }

  public PathTO setDestinationPoint(@Nonnull String destinationPoint) {
    requireNonNull(destinationPoint, "destinationPoint");
    this.destinationPoint = destinationPoint;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getLength() {
    return length;
  }

  public PathTO setLength(@Nonnull Long length) {
    requireNonNull(length, "length");
    this.length = length;
    return this;
  }

  @XmlAttribute(required = true)
  @XmlSchemaType(name = "unsignedInt")
  public Long getMaxVelocity() {
    return maxVelocity;
  }

  public PathTO setMaxVelocity(@Nonnull Long maxVelocity) {
    requireNonNull(maxVelocity, "maxVelocity");
    this.maxVelocity = maxVelocity;
    return this;
  }

  @XmlAttribute(required = true)
  @XmlSchemaType(name = "unsignedInt")
  public Long getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  public PathTO setMaxReverseVelocity(@Nonnull Long maxReverseVelocity) {
    requireNonNull(maxReverseVelocity, "maxReverseVelocity");
    this.maxReverseVelocity = maxReverseVelocity;
    return this;
  }

  @XmlElement(name = "peripheralOperation")
  public List<PeripheralOperationTO> getPeripheralOperations() {
    return peripheralOperations;
  }

  public PathTO setPeripheralOperations(List<PeripheralOperationTO> peripheralOperations) {
    this.peripheralOperations = requireNonNull(peripheralOperations, "peripheralOperations");
    return this;
  }

  @XmlAttribute(required = true)
  public Boolean isLocked() {
    return locked;
  }

  public PathTO setLocked(Boolean locked) {
    this.locked = locked;
    return this;
  }

  @XmlElement(required = true)
  public PathLayout getPathLayout() {
    return pathLayout;
  }

  public PathTO setPathLayout(@Nonnull PathLayout pathLayout) {
    this.pathLayout = requireNonNull(pathLayout, "pathLayout");
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"connectionType", "layerId", "controlPoints"})
  public static class PathLayout {

    private String connectionType = "";
    private Integer layerId = 0;
    private List<ControlPoint> controlPoints = new ArrayList<>();

    @XmlAttribute(required = true)
    public String getConnectionType() {
      return connectionType;
    }

    public PathLayout setConnectionType(@Nonnull String connectionType) {
      this.connectionType = requireNonNull(connectionType, "connectionType");
      return this;
    }

    @XmlAttribute(required = true)
    public Integer getLayerId() {
      return layerId;
    }

    public PathLayout setLayerId(@Nonnull Integer layerId) {
      this.layerId = requireNonNull(layerId, "layerId");
      return this;
    }

    @XmlElement(name = "controlPoint")
    public List<ControlPoint> getControlPoints() {
      return controlPoints;
    }

    public PathLayout setControlPoints(@Nonnull List<ControlPoint> controlPoints) {
      this.controlPoints = requireNonNull(controlPoints, "controlPoints");
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"x", "y"})
  public static class ControlPoint {

    private Long x = 0L;
    private Long y = 0L;

    @XmlAttribute(required = true)
    public Long getX() {
      return x;
    }

    public ControlPoint setX(@Nonnull Long x) {
      this.x = requireNonNull(x, "x");
      return this;
    }

    @XmlAttribute(required = true)
    public Long getY() {
      return y;
    }

    public ControlPoint setY(@Nonnull Long y) {
      this.y = requireNonNull(y, "y");
      return this;
    }
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapterDescription.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle;

import java.util.ResourceBundle;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
import static org.opentcs.virtualvehicle.I18nLoopbackCommAdapter.BUNDLE_PATH;

/**
 * The loopback adapter's {@link VehicleCommAdapterDescription}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackCommunicationAdapterDescription
    extends VehicleCommAdapterDescription {

  @Override
  public String getDescription() {
    return ResourceBundle.getBundle(BUNDLE_PATH)
        .getString("loopbackCommunicationAdapterDescription.description");
  }

  @Override
  public boolean isSimVehicleCommAdapter() {
    return true;
  }

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/PeripheralAttachmentManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentEvent;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
import org.opentcs.drivers.peripherals.management.PeripheralProcessModelEvent;
import org.opentcs.kernel.KernelApplicationConfiguration;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Manages attachment and detachment of peripheral communication adapters to location.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralAttachmentManager
    implements Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralAttachmentManager.class);
  /**
   * This class's configuration.
   */
  private final KernelApplicationConfiguration configuration;
  /**
   * The peripheral service.
   */
  private final InternalPeripheralService peripheralService;
  /**
   * The peripheral controller pool.
   */
  private final LocalPeripheralControllerPool controllerPool;
  /**
   * The peripheral comm adapter registry.
   */
  private final PeripheralCommAdapterRegistry commAdapterRegistry;
  /**
   * The pool of peripheral entries.
   */
  private final PeripheralEntryPool peripheralEntryPool;
  /**
   * The handler to send events to.
   */
  private final EventHandler eventHandler;
  /**
   * Whether the attachment manager is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param peripheralService The peripheral service.
   * @param controllerPool The peripheral controller pool.
   * @param commAdapterRegistry The peripheral comm adapter registry.
   * @param peripheralEntryPool The pool of peripheral entries.
   * @param eventHandler The handler to send events to.
   * @param configuration This class's configuration.
   */
  @Inject
  public PeripheralAttachmentManager(@Nonnull InternalPeripheralService peripheralService,
                                     @Nonnull LocalPeripheralControllerPool controllerPool,
                                     @Nonnull PeripheralCommAdapterRegistry commAdapterRegistry,
                                     @Nonnull PeripheralEntryPool peripheralEntryPool,
                                     @Nonnull @ApplicationEventBus EventHandler eventHandler,
                                     @Nonnull KernelApplicationConfiguration configuration) {
    this.peripheralService = requireNonNull(peripheralService, "peripheralService");
    this.controllerPool = requireNonNull(controllerPool, "controllerPool");
    this.commAdapterRegistry = requireNonNull(commAdapterRegistry, "commAdapterRegistry");
    this.peripheralEntryPool = requireNonNull(peripheralEntryPool, "peripheralEntryPool");
    this.eventHandler = requireNonNull(eventHandler, "eventHandler");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    commAdapterRegistry.initialize();
    peripheralEntryPool.initialize();

    autoAttachAllAdapters();
    LOG.debug("Locations attached: {}", peripheralEntryPool.getEntries());

    if (configuration.autoEnablePeripheralDriversOnStartup()) {
      autoEnableAllAdapters();
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      LOG.debug("Not initialized.");
      return;
    }

    // Disable and terminate all attached drivers to clean up.
    disableAndTerminateAllAdapters();
    peripheralEntryPool.terminate();
    commAdapterRegistry.terminate();

    initialized = false;
  }

  /**
   * Attaches a peripheral comm adapter to a location.
   *
   * @param location The location to attach to.
   * @param description The description of the comm adapter to attach.
   */
  public void attachAdapterToLocation(@Nonnull TCSResourceReference<Location> location,
                                      @Nonnull PeripheralCommAdapterDescription description) {
    requireNonNull(location, "location");
    requireNonNull(description, "description");

    attachAdapterToLocation(peripheralEntryPool.getEntryFor(location),
                            commAdapterRegistry.findFactoryFor(description));
  }

  /**
   * Returns the attachment information for a location.
   *
   * @param location The location to get attachment information about.
   * @return The attachment information for a location.
   */
  @Nonnull
  public PeripheralAttachmentInformation getAttachmentInformation(
      @Nonnull TCSResourceReference<Location> location) {
    requireNonNull(location, "location");

    PeripheralEntry entry = peripheralEntryPool.getEntryFor(location);
    return new PeripheralAttachmentInformation(entry.getLocation(),
                                               entry.getCommAdapterFactory().getDescription());
  }

  private void attachAdapterToLocation(PeripheralEntry entry,
                                       PeripheralCommAdapterFactory factory) {
    Location location = peripheralService.fetchObject(Location.class, entry.getLocation());
    PeripheralCommAdapter commAdapter = factory.getAdapterFor(location);
    if (commAdapter == null) {
      LOG.warn("Factory {} did not provide adapter for location {}, ignoring.",
               factory,
               entry.getLocation().getName());
      return;
    }

    // Perform a cleanup for the old adapter.
    disableAndTerminateAdapter(entry);
    controllerPool.detachPeripheralController(entry.getLocation());

    commAdapter.initialize();
    controllerPool.attachPeripheralController(entry.getLocation(), commAdapter);

    entry.setCommAdapterFactory(factory);
    entry.setCommAdapter(commAdapter);

    // Publish events about the new attached adapter.
    eventHandler.onEvent(new PeripheralAttachmentEvent(
        entry.getLocation(),
        new PeripheralAttachmentInformation(entry.getLocation(),
                                            entry.getCommAdapterFactory().getDescription()))
    );
    eventHandler.onEvent(new PeripheralProcessModelEvent(
        entry.getLocation(),
        PeripheralProcessModel.Attribute.LOCATION.name(),
        entry.getProcessModel()
    ));
  }

  private void autoAttachAdapterToLocation(PeripheralEntry peripheralEntry) {
    // Do not auto-attach if there is already a (real) comm adapter attached to the location.
    if (!(peripheralEntry.getCommAdapter() instanceof NullPeripheralCommAdapter)) {
      return;
    }

    Location location = peripheralService.fetchObject(Location.class,
                                                      peripheralEntry.getLocation());
    List<PeripheralCommAdapterFactory> factories = commAdapterRegistry.findFactoriesFor(location);
    if (!factories.isEmpty()) {
      LOG.debug("Attaching {} to first available adapter: {}.",
                peripheralEntry.getLocation().getName(),
                factories.get(0).getDescription().getDescription());
      attachAdapterToLocation(peripheralEntry, factories.get(0));
    }
  }

  private void autoAttachAllAdapters() {
    peripheralEntryPool.getEntries().forEach((location, entry) -> {
      autoAttachAdapterToLocation(entry);
    });
  }

  private void disableAndTerminateAdapter(PeripheralEntry peripheralEntry) {
    peripheralEntry.getCommAdapter().disable();
    peripheralEntry.getCommAdapter().terminate();
  }

  private void autoEnableAllAdapters() {
    peripheralEntryPool.getEntries().values().stream()
        .map(entry -> entry.getCommAdapter())
        .filter(adapter -> !adapter.isEnabled())
        .forEach(adapter -> adapter.enable());
  }

  private void disableAndTerminateAllAdapters() {
    LOG.debug("Detaching peripheral communication adapters...");
    peripheralEntryPool.getEntries().forEach((location, entry) -> {
      disableAndTerminateAdapter(entry);
    });
    LOG.debug("Detached peripheral communication adapters");
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/KernelStarter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import java.io.IOException;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.access.LocalKernel;
import org.opentcs.components.kernel.KernelExtension;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.customizations.kernel.ActiveInAllModes;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Initializes an openTCS kernel instance.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class KernelStarter {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(KernelStarter.class);
  /**
   * The kernel we're working with.
   */
  private final LocalKernel kernel;
  /**
   * The plant model service.
   */
  private final InternalPlantModelService plantModelService;
  /**
   * The kernel extensions to be registered.
   */
  private final Set<KernelExtension> extensions;
  /**
   * The kernel's executor service.
   */
  private final ScheduledExecutorService kernelExecutor;

  /**
   * Creates a new instance.
   *
   * @param kernel The kernel we're working with.
   * @param plantModelService The plant model service.
   * @param extensions The kernel extensions to be registered.
   * @param kernelExecutor The kernel's executor service.
   */
  @Inject
  protected KernelStarter(LocalKernel kernel,
                          InternalPlantModelService plantModelService,
                          @ActiveInAllModes Set<KernelExtension> extensions,
                          @KernelExecutor ScheduledExecutorService kernelExecutor) {
    this.kernel = requireNonNull(kernel, "kernel");
    this.plantModelService = requireNonNull(plantModelService, "plantModelService");
    this.extensions = requireNonNull(extensions, "extensions");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
  }

  /**
   * Initializes the system and starts the openTCS kernel including modules.
   *
   * @throws IOException If there was a problem loading model data.
   */
  public void startKernel()
      throws IOException {
    kernelExecutor.submit(() -> {
      // Register kernel extensions.
      for (KernelExtension extension : extensions) {
        kernel.addKernelExtension(extension);
      }

      // Start local kernel.
      kernel.initialize();
      LOG.debug("Kernel initialized.");

      plantModelService.loadPlantModel();
      LOG.info("Loaded model named '{}'.", plantModelService.getModelName());

      kernel.setState(Kernel.State.OPERATING);
    });
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/PathConnection.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import com.google.inject.assistedinject.Assisted;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.util.Collection;
import java.util.EventObject;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.StringJoiner;
import javax.inject.Inject;
import org.jhotdraw.draw.AttributeKey;
import org.jhotdraw.draw.AttributeKeys;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.connector.ChopEllipseConnector;
import org.jhotdraw.draw.connector.Connector;
import org.jhotdraw.draw.handle.BezierOutlineHandle;
import org.jhotdraw.draw.handle.Handle;
import org.jhotdraw.draw.liner.ElbowLiner;
import org.jhotdraw.draw.liner.Liner;
import org.jhotdraw.draw.liner.SlantedLiner;
import org.jhotdraw.geom.BezierPath;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.components.drawing.DrawingOptions;
import org.opentcs.guing.components.drawing.Strokes;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.drawing.figures.liner.BezierLinerControlPointHandle;
import org.opentcs.guing.components.drawing.figures.liner.PolyPathLiner;
import org.opentcs.guing.components.drawing.figures.liner.TripleBezierLiner;
import org.opentcs.guing.components.drawing.figures.liner.TupelBezierLiner;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.type.AbstractProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.SpeedProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A connection between two points.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PathConnection
    extends SimpleLineConnection {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PathConnection.class);
  /**
   * The dash pattern for locked paths.
   */
  private static final double[] LOCKED_DASH = {6.0, 4.0};
  /**
   * The dash pattern for unlocked paths.
   */
  private static final double[] UNLOCKED_DASH = {10.0, 0.0};
  /**
   * The tool tip text generator.
   */
  private final ToolTipTextGenerator textGenerator;
  /**
   * The drawing options.
   */
  private final DrawingOptions drawingOptions;
  /**
   * Control point 1.
   */
  private Point2D.Double cp1;
  /**
   * Control point 2.
   */
  private Point2D.Double cp2;
  /**
   * Control point 3.
   */
  private Point2D.Double cp3;
  /**
   * Control point 4.
   */
  private Point2D.Double cp4;
  /**
   * Control point 5.
   */
  private Point2D.Double cp5;

  private Origin previousOrigin;

  /**
   * Creates a new instance.
   *
   * @param model The model corresponding to this graphical object.
   * @param textGenerator The tool tip text generator.
   * @param drawingOptions The drawing options.
   */
  @Inject
  public PathConnection(@Assisted PathModel model,
                        ToolTipTextGenerator textGenerator,
                        DrawingOptions drawingOptions) {
    super(model);
    this.textGenerator = requireNonNull(textGenerator, "textGenerator");
    this.drawingOptions = requireNonNull(drawingOptions, "drawingOptions");
    resetPath();
  }

  @Override
  public PathModel getModel() {
    return (PathModel) get(FigureConstants.MODEL);
  }

  @Override
  public void updateConnection() {
    super.updateConnection();
    initializePreviousOrigin();
    updateControlPoints();
  }

  /**
   * Resets control points and connects start and end point with a straight line.
   */
  private void resetPath() {
    Point2D.Double sp = path.get(0, BezierPath.C0_MASK);
    Point2D.Double ep = path.get(path.size() - 1, BezierPath.C0_MASK);

    path.clear();
    path.add(new BezierPath.Node(sp));
    path.add(new BezierPath.Node(ep));
    cp1 = null;
    cp2 = null;
    cp3 = null;
    cp4 = null;
    cp5 = null;
    getModel().getPropertyPathControlPoints().markChanged();
  }

  /**
   * Initialise the control points when converting into BEZIER curve.
   *
   * @param type the type of the curve
   */
  private void initControlPoints(PathModel.Type type) {
    Point2D.Double sp = path.get(0, BezierPath.C0_MASK);
    Point2D.Double ep = path.get(path.size() - 1, BezierPath.C0_MASK);

    if (sp.x != ep.x || sp.y != ep.y) {
      path.clear();
      if (type == PathModel.Type.BEZIER_3) { //BEZIER curve with 3 control points);
        //Add the scaled vector between start and endpoint to the startpoint
        cp1 = new Point2D.Double(sp.x + (ep.x - sp.x) * 1 / 6, sp.y + (ep.y - sp.y) * 1 / 6); //point at 1/6
        cp2 = new Point2D.Double(sp.x + (ep.x - sp.x) * 2 / 6, sp.y + (ep.y - sp.y) * 2 / 6); //point at 2/6
        cp3 = new Point2D.Double(sp.x + (ep.x - sp.x) * 3 / 6, sp.y + (ep.y - sp.y) * 3 / 6); //point at 3/6
        cp4 = new Point2D.Double(sp.x + (ep.x - sp.x) * 4 / 6, sp.y + (ep.y - sp.y) * 4 / 6); //point at 4/6
        cp5 = new Point2D.Double(sp.x + (ep.x - sp.x) * 5 / 6, sp.y + (ep.y - sp.y) * 5 / 6); //point at 5/6
        path.add(new BezierPath.Node(BezierPath.C2_MASK,
                                     sp.x, sp.y, //Current point
                                     sp.x, sp.y, //Previous point - not in use because of C2_MASK
                                     cp1.x, cp1.y)); //Next point
        //Use cp1 and cp2 to draw between sp and cp3
        path.add(new BezierPath.Node(BezierPath.C1C2_MASK,
                                     cp3.x, cp3.y, //Current point
                                     cp2.x, cp2.y, //Previous point
                                     cp4.x, cp4.y)); //Next point
        //Use cp4 and cp5 to draw between cp3 and ep
        path.add(new BezierPath.Node(BezierPath.C1_MASK,
                                     ep.x, ep.y, //Current point
                                     cp5.x, cp5.y, //Previous point
                                     ep.x, ep.y)); //Next point - not in use because of C1_MASK
      }
      else {
        cp1 = new Point2D.Double(sp.x + (ep.x - sp.x) / 3, sp.y + (ep.y - sp.y) / 3); //point at 1/3
        cp2 = new Point2D.Double(ep.x - (ep.x - sp.x) / 3, ep.y - (ep.y - sp.y) / 3); //point at 2/3
        cp3 = null;
        cp4 = null;
        cp5 = null;
        path.add(new BezierPath.Node(BezierPath.C2_MASK,
                                     sp.x, sp.y, //Current point
                                     sp.x, sp.y, //Previous point - not in use because of C2_MASK
                                     cp1.x, cp1.y)); //Next point
        path.add(new BezierPath.Node(BezierPath.C1_MASK,
                                     ep.x, ep.y, //Current point
                                     cp2.x, cp2.y, //Previous point
                                     ep.x, ep.y)); //Next point - not in use because of C1_MASK
      }

      getModel().getPropertyPathControlPoints().markChanged();
      path.invalidatePath();
    }
  }

  /**
   * Add control points.
   *
   * @param cp1 First control point.
   * @param cp2 Identical with cp1 for quadratic curves.
   */
  public void addControlPoints(Point2D.Double cp1, Point2D.Double cp2) {
    this.cp1 = cp1;
    this.cp2 = cp2;
    this.cp3 = null;
    Point2D.Double sp = path.get(0, BezierPath.C0_MASK);
    Point2D.Double ep = path.get(1, BezierPath.C0_MASK);
    path.clear();
    path.add(new BezierPath.Node(BezierPath.C2_MASK,
                                 sp.x, sp.y, //Current point
                                 sp.x, sp.y, //Previous point
                                 cp1.x, cp1.y)); //Next point
    path.add(new BezierPath.Node(BezierPath.C1_MASK,
                                 ep.x, ep.y, //Current point
                                 cp2.x, cp2.y, //Previous point
                                 ep.x, ep.y)); //Next point
  }

  /**
   * A bezier curve with three control points.
   *
   * @param cp1 Control point 1
   * @param cp2 Control point 2
   * @param cp3 Control point 3
   * @param cp4 Control point 4
   * @param cp5 Control point 5
   */
  public void addControlPoints(Point2D.Double cp1,
                               Point2D.Double cp2,
                               Point2D.Double cp3,
                               Point2D.Double cp4,
                               Point2D.Double cp5) {
    this.cp1 = cp1;
    this.cp2 = cp2;
    this.cp3 = cp3;
    this.cp4 = cp4;
    this.cp5 = cp5;
    Point2D.Double sp = path.get(0, BezierPath.C0_MASK);
    Point2D.Double ep = path.get(path.size() - 1, BezierPath.C0_MASK);
    path.clear();
    path.add(new BezierPath.Node(BezierPath.C2_MASK,
                                 sp.x, sp.y, //Current point
                                 sp.x, sp.y, //Previous point
                                 cp1.x, cp1.y)); //Next point
    //Use cp1 and cp2 to draw between sp and cp3
    path.add(new BezierPath.Node(BezierPath.C1C2_MASK,
                                 cp3.x, cp3.y, //Current point
                                 cp2.x, cp2.y, //Previous point
                                 cp4.x, cp4.y)); //Next point
    //Use cp4 and cp5 to draw between cp3 and ep
    path.add(new BezierPath.Node(BezierPath.C1_MASK,
                                 ep.x, ep.y, //Current point
                                 cp5.x, cp5.y, //Previous point
                                 cp4.x, cp4.y)); //Next point
    StringProperty sProp = getModel().getPropertyPathControlPoints();
    sProp.setText(String.format("%d,%d;%d,%d;%d,%d;%d,%d;%d,%d;",
                                (int) cp1.x, (int) cp1.y,
                                (int) cp2.x, (int) cp2.y,
                                (int) cp3.x, (int) cp3.y,
                                (int) cp4.x, (int) cp4.y,
                                (int) cp5.x, (int) cp5.y));
    sProp.markChanged();
    getModel().propertiesChanged(this);
  }

  public Point2D.Double getCp1() {
    return cp1;
  }

  public Point2D.Double getCp2() {
    return cp2;
  }

  public Point2D.Double getCp3() {
    return cp3;
  }

  public Point2D.Double getCp4() {
    return cp4;
  }

  public Point2D.Double getCp5() {
    return cp5;
  }

  @Override
  public Point2D.Double getCenter() {
    // Computes the center of the curve.
    // Approximation: Center of the control points.
    Point2D.Double p1;
    Point2D.Double p2;
    Point2D.Double pc;

    p1 = (cp1 == null ? path.get(0, BezierPath.C0_MASK) : cp1);
    p2 = (cp2 == null ? path.get(1, BezierPath.C0_MASK) : cp2);
    if (cp3 == null) {
      pc = new Point2D.Double((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
    }
    else {
      //Use cp3 for 3-bezier as center because the curve goes through it at 50%
      pc = (cp3 == null ? path.get(3, BezierPath.C0_MASK) : cp3);
    }

    return pc;
  }

  @Override
  public int getLayer() {
    return getModel().getPropertyLayerWrapper().getValue().getLayer().getOrdinal();
  }

  @Override
  public boolean isVisible() {
    return super.isVisible()
        && getModel().getPropertyLayerWrapper().getValue().getLayer().isVisible()
        && getModel().getPropertyLayerWrapper().getValue().getLayerGroup().isVisible();
  }

  /**
   * Initializes the previous origin which is used to scale the control points of this path.
   */
  private void initializePreviousOrigin() {
    if (previousOrigin == null) {
      Origin origin = get(FigureConstants.ORIGIN);
      previousOrigin = new Origin();
      previousOrigin.setScale(origin.getScaleX(), origin.getScaleY());
    }
  }

  /**
   * Update bezier and polypath control points.
   */
  public void updateControlPoints() {
    String sControlPoints = "";
    if (getLinerType() == PathModel.Type.POLYPATH) {
      sControlPoints = updatePolyPathControlPoints();
    }
    else if (getLinerType() == PathModel.Type.BEZIER || getLinerType() == PathModel.Type.BEZIER_3) {
      sControlPoints = updateBezierControlPoints();
    }

    StringProperty sProp = getModel().getPropertyPathControlPoints();
    sProp.setText(sControlPoints);
    invalidate();
    sProp.markChanged();
    getModel().propertiesChanged(this);
  }

  private String updatePolyPathControlPoints() {
    StringJoiner rtn = new StringJoiner(";");
    for (int i = 1; i < path.size() - 1; i++) {
      Point2D.Double p = path.get(i, BezierPath.C0_MASK);
      rtn.add(String.format("%d,%d", (int) p.x, (int) p.y));
    }
    return rtn.toString();
  }

  private String updateBezierControlPoints() {
    if (cp1 != null && cp2 != null) {
      if (cp3 != null) {
        cp1 = path.get(0, BezierPath.C2_MASK);
        cp2 = path.get(1, BezierPath.C1_MASK);
        cp3 = path.get(1, BezierPath.C0_MASK);
        cp4 = path.get(1, BezierPath.C2_MASK);
        cp5 = path.get(2, BezierPath.C1_MASK);
      }
      else {
        cp1 = path.get(0, BezierPath.C2_MASK);
        cp2 = path.get(1, BezierPath.C1_MASK);
      }
    }
    String sControlPoints = "";
    if (cp1 != null) {
      if (cp2 != null) {
        if (cp3 != null) {
          // Format: x1,y1;x2,y2;x3,y3;x4,y4;x5,y5
          sControlPoints = String.format("%d,%d;%d,%d;%d,%d;%d,%d;%d,%d",
                                         (int) (cp1.x),
                                         (int) (cp1.y),
                                         (int) (cp2.x),
                                         (int) (cp2.y),
                                         (int) (cp3.x),
                                         (int) (cp3.y),
                                         (int) (cp4.x),
                                         (int) (cp4.y),
                                         (int) (cp5.x),
                                         (int) (cp5.y));
        }
        else {
          // Format: x1,y1;x2,y2
          sControlPoints = String.format("%d,%d;%d,%d", (int) (cp1.x),
                                         (int) (cp1.y), (int) (cp2.x),
                                         (int) (cp2.y));
        }
      }
      else {
        // Format: x1,y1
        sControlPoints = String.format("%d,%d", (int) (cp1.x), (int) (cp1.y));
      }
    }
    return sControlPoints;
  }

  /**
   * Connects two figures with this connection.
   *
   * @param start The first figure.
   * @param end The second figure.
   */
  public void connect(LabeledPointFigure start, LabeledPointFigure end) {
    Connector compConnector = new ChopEllipseConnector();
    Connector startConnector = start.findCompatibleConnector(compConnector, true);
    Connector endConnector = end.findCompatibleConnector(compConnector, true);

    if (!canConnect(startConnector, endConnector)) {
      return;
    }

    setStartConnector(startConnector);
    setEndConnector(endConnector);

    getModel().setConnectedComponents(start.get(FigureConstants.MODEL),
                                      end.get(FigureConstants.MODEL));
  }

  /**
   * Returns the type of this path.
   *
   * @return The type of this path
   */
  public PathModel.Type getLinerType() {
    return (PathModel.Type) getModel().getPropertyPathConnType().getValue();
  }

  public void setLinerByType(PathModel.Type type) {
    switch (type) {
      case DIRECT:
        resetPath();
        updateLiner(null);
        break;

      case ELBOW:
        if (!(getLiner() instanceof ElbowLiner)) {
          resetPath();
          updateLiner(new ElbowLiner());
        }

        break;

      case SLANTED:
        if (!(getLiner() instanceof SlantedLiner)) {
          resetPath();
          updateLiner(new SlantedLiner());
        }

        break;

      case BEZIER:
        if (!(getLiner() instanceof TupelBezierLiner)) {
          initControlPoints(type);
          updateLiner(new TupelBezierLiner());
        }
        break;
      case BEZIER_3:
        if (!(getLiner() instanceof TripleBezierLiner)) {
          initControlPoints(type);
          updateLiner(new TripleBezierLiner());
        }
        break;
      case POLYPATH:
        if (!(getLiner() instanceof PolyPathLiner)) {
          initPolyPath();
          updateLiner(new PolyPathLiner());
        }
        break;
      default:
        setLiner(null);
    }
  }

  private void updateLiner(Liner newLiner) {
    setLiner(newLiner);
    fireFigureHandlesChanged();
    fireAreaInvalidated();
    updateControlPoints();
    invalidate();
    getModel().propertiesChanged(this);
  }

  private LengthProperty calculateLength() {
    try {
      LengthProperty property = getModel().getPropertyLength();

      if (property != null) {
        double length = (double) property.getValue();
        if (length <= 0.0) {
          PointFigure start = ((LabeledPointFigure) getStartFigure()).getPresentationFigure();
          PointFigure end = ((LabeledPointFigure) getEndFigure()).getPresentationFigure();
          double startPosX = start.getModel().getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM);
          double startPosY = start.getModel().getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM);
          double endPosX = end.getModel().getPropertyModelPositionX().getValueByUnit(LengthProperty.Unit.MM);
          double endPosY = end.getModel().getPropertyModelPositionY().getValueByUnit(LengthProperty.Unit.MM);
          length = distance(startPosX, startPosY, endPosX, endPosY);
          property.setValueAndUnit(length, LengthProperty.Unit.MM);
          property.markChanged();
        }
      }

      return property;
    }
    catch (IllegalArgumentException ex) {
      LOG.error("calculateLength()", ex);
      return null;
    }
  }

  @Override
  public String getToolTipText(Point2D.Double p) {
    return textGenerator.getToolTipText(getModel());
  }

  /**
   * Checks whether two points can be connected with each other.
   *
   * @param start The start connector.
   * @param end The end connector.
   * @return {@code true}, if the two points can be connected, otherwise {@code false}.
   */
  @Override
  public boolean canConnect(Connector start, Connector end) {
    ModelComponent modelStart = start.getOwner().get(FigureConstants.MODEL);
    ModelComponent modelEnd = end.getOwner().get(FigureConstants.MODEL);

    return modelStart instanceof PointModel
        && modelEnd instanceof PointModel
        && modelStart != modelEnd;
  }

  @Override
  public Collection<Handle> createHandles(int detailLevel) {
    List<Handle> handles = new LinkedList<>();

    if (!isVisible()) {
      return handles;
    }

    // see BezierFigure
    switch (detailLevel % 2) {
      case -1: // Mouse hover handles
        handles.add(new BezierOutlineHandle(this, true));
        break;

      case 0:  // Mouse clicked
        if (getLinerType() == PathModel.Type.POLYPATH) {
          for (int i = 1; i < path.size() - 1; i++) {
            handles.add(new BezierLinerControlPointHandle(this, i, BezierPath.C0_MASK));
          }
        }
        else {
          if (cp1 != null) {
            // Start point: handle to CP2
            handles.add(new BezierLinerControlPointHandle(this, 0, BezierPath.C2_MASK));
            if (cp2 != null) {
              // End point: handle to CP3
              handles.add(new BezierLinerControlPointHandle(this, 1, BezierPath.C1_MASK));
              if (cp3 != null) {
                // End point: handle to EP
                handles.add(new BezierLinerControlPointHandle(this, 2, BezierPath.C1_MASK));
              }
            }
          }
        }

        break;

      case 1:  // double click
        handles.add(new BezierOutlineHandle(this));
        break;

      default:
    }

    return handles;
  }

  @Override
  public void lineout() {
    if (getLiner() == null) {
      path.invalidatePath();
    }
    else {
      getLiner().lineout(this);
    }
  }

  @Override
  public void propertiesChanged(AttributesChangeEvent e) {
    if (!e.getInitiator().equals(this)) {
      setLinerByType((PathModel.Type) getModel().getPropertyPathConnType().getValue());
      calculateLength();
      lineout();
    }

    super.propertiesChanged(e);
  }

  @Override
  public void draw(Graphics2D g) {
    if (drawingOptions.isBlocksVisible()) {
      drawBlockDecoration(g);
    }
    drawRouteDecoration(g);

    super.draw(g);
  }

  private void drawRouteDecoration(Graphics2D g) {
    for (VehicleModel vehicleModel : getModel().getVehicleModels()) {
      Stroke stroke = Strokes.PATH_ON_ROUTE;
      Color color = transparentColor(vehicleModel.getDriveOrderColor(), 192);
      if (vehicleModel.getDriveOrderState() == TransportOrder.State.WITHDRAWN) {
        stroke = Strokes.PATH_ON_WITHDRAWN_ROUTE;
        color = Color.GRAY;
      }

      drawDecoration(g, stroke, color);
    }
  }

  private void drawBlockDecoration(Graphics2D g) {
    for (BlockModel blockModel : getModel().getBlockModels()) {
      drawDecoration(g, Strokes.BLOCK_ELEMENT, transparentColor(blockModel.getColor(), 192));
    }
  }

  private Color transparentColor(Color color, int alpha) {
    return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
  }

  private void drawDecoration(Graphics2D g, Stroke stroke, Color color) {
    g.setStroke(stroke);
    g.setColor(color);
    g.draw(this.getShape());
  }

  @Override
  public void updateDecorations() {
    if (getModel() == null) {
      return;
    }

    set(AttributeKeys.START_DECORATION, navigableBackward() ? ARROW_BACKWARD : null);
    set(AttributeKeys.END_DECORATION, navigableForward() ? ARROW_FORWARD : null);

    // Mark locked path.
    if (Boolean.TRUE.equals(getModel().getPropertyLocked().getValue())) {
      set(AttributeKeys.STROKE_COLOR, Color.red);
      set(AttributeKeys.STROKE_DASHES, LOCKED_DASH);
    }
    else {
      set(AttributeKeys.STROKE_COLOR, Color.black);
      set(AttributeKeys.STROKE_DASHES, UNLOCKED_DASH);
    }
  }

  @Override
  public <T> void set(AttributeKey<T> key, T newValue) {
    super.set(key, newValue);
    // if the ModelComponent is set we update the decorations, because
    // properties like maxReverseVelocity could have changed
    if (key.equals(FigureConstants.MODEL)) {
      updateDecorations();
    }
  }

  @Override
  public void updateModel() {
    if (calculateLength() == null) {
      return;
    }

    getModel().getPropertyMaxVelocity().markChanged();
    getModel().getPropertyMaxReverseVelocity().markChanged();

    getModel().propertiesChanged(this);
  }

  @Override
  public void scaleModel(EventObject event) {
    if (!(event.getSource() instanceof Origin)) {
      return;
    }

    Origin origin = (Origin) event.getSource();
    if (previousOrigin.getScaleX() == origin.getScaleX()
        && previousOrigin.getScaleY() == origin.getScaleY()) {
      return;
    }

    if (isTupelBezier()) { // BEZIER
      Point2D.Double scaledControlPoint = scaleControlPoint(cp1, origin);
      path.set(0, BezierPath.C2_MASK, scaledControlPoint);
      scaledControlPoint = scaleControlPoint(cp2, origin);
      path.set(1, BezierPath.C1_MASK, scaledControlPoint);
    }
    else if (isTripleBezier()) { // BEZIER_3
      Point2D.Double scaledControlPoint = scaleControlPoint(cp1, origin);
      path.set(0, BezierPath.C2_MASK, scaledControlPoint);
      scaledControlPoint = scaleControlPoint(cp2, origin);
      path.set(1, BezierPath.C1_MASK, scaledControlPoint);
      scaledControlPoint = scaleControlPoint(cp3, origin);
      path.set(1, BezierPath.C0_MASK, scaledControlPoint);
      scaledControlPoint = scaleControlPoint(cp4, origin);
      path.set(1, BezierPath.C2_MASK, scaledControlPoint);
      path.set(2, BezierPath.C2_MASK, scaledControlPoint);
      scaledControlPoint = scaleControlPoint(cp5, origin);
      path.set(2, BezierPath.C1_MASK, scaledControlPoint);
    }

    // Remember the new scale
    previousOrigin.setScale(origin.getScaleX(), origin.getScaleY());
    updateControlPoints();
  }

  private boolean navigableForward() {
    return getModel().getPropertyMaxVelocity().getValueByUnit(SpeedProperty.Unit.MM_S) > 0.0;
  }

  private boolean navigableBackward() {
    return getModel().getPropertyMaxReverseVelocity().getValueByUnit(SpeedProperty.Unit.MM_S) > 0.0;
  }

  private Point2D.Double scaleControlPoint(Point2D.Double p, Origin newScale) {
    return new Double((p.x * previousOrigin.getScaleX()) / newScale.getScaleX(),
                      (p.y * previousOrigin.getScaleY()) / newScale.getScaleY());
  }

  private boolean isTupelBezier() {
    return cp1 != null && cp2 != null && cp3 == null && cp4 == null && cp5 == null;
  }

  private boolean isTripleBezier() {
    return cp1 != null && cp2 != null && cp3 != null && cp4 != null && cp5 != null;
  }

  @Override // LineConnectionFigure
  public PathConnection clone() {
    PathConnection clone = (PathConnection) super.clone();

    AbstractProperty pConnType = (AbstractProperty) clone.getModel().getPropertyPathConnType();
    if (getLiner() instanceof TupelBezierLiner) {
      pConnType.setValue(PathModel.Type.BEZIER);
    }
    else if (getLiner() instanceof TripleBezierLiner) {
      pConnType.setValue(PathModel.Type.BEZIER_3);
    }
    else if (getLiner() instanceof ElbowLiner) {
      pConnType.setValue(PathModel.Type.ELBOW);
    }
    else if (getLiner() instanceof SlantedLiner) {
      pConnType.setValue(PathModel.Type.SLANTED);
    }

    return clone;
  }

  private void initPolyPath() {
    Point2D.Double sp = path.get(0, BezierPath.C0_MASK);
    Point2D.Double ep = path.get(path.size() - 1, BezierPath.C0_MASK);

    if (sp.x == ep.x && sp.y == ep.y) {
      path.clear();
      path.add(sp);
      String[] coords = getModel().getPropertyPathControlPoints().getText().split("[;]");
      for (String coordinates : coords) {
        String[] c = coordinates.split("[,]");
        int x = (int) java.lang.Double.parseDouble(c[0]);
        int y = (int) java.lang.Double.parseDouble(c[1]);
        path.add(x, y);
      }

      path.add(ep);
    }
    else {

      path.clear();
      path.add(new BezierPath.Node(sp));
      path.add(new BezierPath.Node((sp.x + ep.x) / 2.0, (sp.y + ep.y) / 2.0));
      path.add(new BezierPath.Node(ep));
    }
  }

  @Override // SimpleLineConnection
  public boolean handleMouseClick(Point2D.Double p, MouseEvent evt, DrawingView drawingView) {
    if (getLinerType() == PathModel.Type.POLYPATH) {
      int addPointMask = MouseEvent.CTRL_DOWN_MASK;
      int deletePointMask = MouseEvent.ALT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK;
      if ((evt.getModifiersEx() & (addPointMask | deletePointMask)) == addPointMask) {
        int index = path.findSegment(p, 10);
        if (index != -1) {
          path.add(index + 1, new BezierPath.Node(p));
          updateConnection();
        }
      }
      else if ((evt.getModifiersEx() & (deletePointMask | addPointMask)) == deletePointMask) {
        int index = path.findSegment(p, 10);
        if (index != -1) {
          Point2D.Double[] points = path.toPolygonArray();
          path.clear();
          for (int i = 0; i < points.length; i++) {
            if (i != index) {
              path.add(new BezierPath.Node(points[i]));
            }
          }
          updateConnection();
        }
      }
    }
    return false;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/DefaultParkingPositionSupplier.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static org.opentcs.components.kernel.Dispatcher.PROPKEY_ASSIGNED_PARKING_POSITION;
import static org.opentcs.components.kernel.Dispatcher.PROPKEY_PREFERRED_PARKING_POSITION;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A parking position supplier that tries to find parking positions that are unoccupied,
 * not on the current route of any other vehicle and as close as possible to the
 * parked vehicle's current position.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultParkingPositionSupplier
    extends AbstractParkingPositionSupplier {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultParkingPositionSupplier.class);

  /**
   * Creates a new instance.
   *
   * @param plantModelService The plant model service.
   * @param router A router for computing travel costs to parking positions.
   */
  @Inject
  public DefaultParkingPositionSupplier(InternalPlantModelService plantModelService,
                                        Router router) {
    super(plantModelService, router);
  }

  @Override
  public Optional<Point> findParkingPosition(final Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");

    if (vehicle.getCurrentPosition() == null) {
      return Optional.empty();
    }

    Set<Point> parkingPosCandidates = findUsableParkingPositions(vehicle);

    if (parkingPosCandidates.isEmpty()) {
      LOG.debug("No parking position candidates found.");
      return Optional.empty();
    }

    // Check if the vehicle has an assigned parking position.
    // If yes, return either that (if it's with the available points) or none.
    String assignedParkingPosName = vehicle.getProperty(PROPKEY_ASSIGNED_PARKING_POSITION);
    if (assignedParkingPosName != null) {
      return Optional.ofNullable(pickPointWithName(assignedParkingPosName, parkingPosCandidates));
    }

    // Check if the vehicle has a preferred parking position.
    // If yes, and if it's with the available points, return that.
    String preferredParkingPosName = vehicle.getProperty(PROPKEY_PREFERRED_PARKING_POSITION);
    if (preferredParkingPosName != null) {
      Point preferredPoint = pickPointWithName(preferredParkingPosName, parkingPosCandidates);
      if (preferredPoint != null) {
        return Optional.of(preferredPoint);
      }
    }

    Point nearestPoint = nearestPoint(vehicle, parkingPosCandidates);
    LOG.debug("Selected parking position {} for vehicle {} from candidates {}.",
              nearestPoint,
              vehicle.getName(),
              parkingPosCandidates);
    return Optional.ofNullable(nearestPoint);
  }

  @Nullable
  private Point pickPointWithName(String name, Set<Point> points) {
    return points.stream()
        .filter(point -> name.equals(point.getName()))
        .findAny()
        .orElse(null);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/LocalPeripheralControllerPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralControllerPool;

/**
 * Manages the attachment of peripheral controllers to locations and peripheral comm adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LocalPeripheralControllerPool
    extends PeripheralControllerPool,
            Lifecycle {

  /**
   * Associates a peripheral controller with a location and a comm adapter.
   *
   * @param location The reference to the location.
   * @param commAdapter The comm adapter that is going to control the peripheral deivce.
   * @throws IllegalArgumentException If the referenced location does not exist.
   */
  void attachPeripheralController(TCSResourceReference<Location> location,
                                  PeripheralCommAdapter commAdapter)
      throws IllegalArgumentException;

  /**
   * Disassociates a peripheral controller and a comm adapter from a location.
   *
   * @param location The reference to the location.
   */
  void detachPeripheralController(TCSResourceReference<Location> location);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/ImplicitDispatchTrigger.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import static java.util.Objects.requireNonNull;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.model.Vehicle;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An event listener that triggers dispatching of vehicles and transport orders on certain events.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ImplicitDispatchTrigger
    implements EventHandler {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ImplicitDispatchTrigger.class);
  /**
   * The dispatcher in use.
   */
  private final Dispatcher dispatcher;

  /**
   * Creates a new instance.
   *
   * @param dispatcher The dispatcher in use.
   */
  public ImplicitDispatchTrigger(Dispatcher dispatcher) {
    this.dispatcher = requireNonNull(dispatcher, "dispatcher");
  }

  @Override
  public void onEvent(Object event) {
    if (!(event instanceof TCSObjectEvent)) {
      return;
    }
    TCSObjectEvent objectEvent = (TCSObjectEvent) event;
    if (objectEvent.getCurrentOrPreviousObjectState() instanceof Vehicle) {
      checkVehicleChange((Vehicle) objectEvent.getPreviousObjectState(),
                         (Vehicle) objectEvent.getCurrentObjectState());
    }
  }

  private void checkVehicleChange(Vehicle oldVehicle, Vehicle newVehicle) {
    if ((newVehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_UTILIZED
         || newVehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_RESPECTED)
        && (idleAndEnergyLevelChanged(oldVehicle, newVehicle)
            || awaitingNextOrder(oldVehicle, newVehicle)
            || orderSequenceNulled(oldVehicle, newVehicle))) {
      LOG.debug("Dispatching for {}...", newVehicle);
      dispatcher.dispatch();
    }
  }

  private boolean idleAndEnergyLevelChanged(Vehicle oldVehicle, Vehicle newVehicle) {
    // If the vehicle is idle and its energy level changed, we may want to order it to recharge.
    return newVehicle.hasProcState(Vehicle.ProcState.IDLE)
        && (newVehicle.hasState(Vehicle.State.IDLE) || newVehicle.hasState(Vehicle.State.CHARGING))
        && newVehicle.getEnergyLevel() != oldVehicle.getEnergyLevel();
  }

  private boolean awaitingNextOrder(Vehicle oldVehicle, Vehicle newVehicle) {
    // If the vehicle's processing state changed to IDLE or AWAITING_ORDER, it is waiting for
    // its next order, so look for one.
    return newVehicle.getProcState() != oldVehicle.getProcState()
        && (newVehicle.hasProcState(Vehicle.ProcState.IDLE)
            || newVehicle.hasProcState(Vehicle.ProcState.AWAITING_ORDER));
  }

  private boolean orderSequenceNulled(Vehicle oldVehicle, Vehicle newVehicle) {
    // If the vehicle's order sequence reference has become null, the vehicle has just been released
    // from an order sequence, so we may look for new assignments.
    return newVehicle.getOrderSequence() == null
        && oldVehicle.getOrderSequence() != null;
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/gui/package-info.java<|end_filename|>
/**
 * Supportive classes for graphical frontends.
 */
package org.opentcs.util.gui;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/notification/package-info.java<|end_filename|>
/**
 * Classes for storing user-targeted notifications.
 */
package org.opentcs.data.notification;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/SharedKernelServicePortalProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

import org.opentcs.components.kernel.services.ServiceUnavailableException;

/**
 * Pools access to a {@link KernelServicePortal} instance for multiple clients.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface SharedKernelServicePortalProvider {

  /**
   * Creates and registers a new client with this access pool.
   * This is a convenience method that supports try-with-ressources and does not require a
   * preexisting client.
   *
   * @return The {@link SharedKernelServicePortal}.
   * @throws ServiceUnavailableException in case of connection falure with the portal.
   */
  SharedKernelServicePortal register()
      throws ServiceUnavailableException;

  /**
   * Checks whether a kernel reference is currently being shared.
   *
   * @return {@code true} if, and only if, a portal reference is currently being shared, meaning
   * that at least one client is registered and a usable portal reference exists.
   */
  boolean portalShared();

  /**
   * Returns a description for the portal currently being shared.
   *
   * @return A description for the portal currently being shared, or the empty string, if none is
   * currently being shared.
   */
  String getPortalDescription();
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/persistence/XMLFileModelPersister.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.persistence;

import static com.google.common.base.Strings.emptyToNull;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import static java.util.Optional.ofNullable;
import javax.inject.Inject;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.customizations.ApplicationHome;
import static org.opentcs.util.Assertions.checkState;
import org.opentcs.util.FileSystems;
import org.opentcs.util.persistence.ModelParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A ModelPersister implementation realizing persistence of models with XML
 * files.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class XMLFileModelPersister
    implements ModelPersister {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(XMLFileModelPersister.class);
  /**
   * The name of the model file in the model directory.
   */
  private static final String MODEL_FILE_NAME = "model.xml";
  /**
   * The directory path for the persisted model.
   */
  private final File dataDirectory;
  /**
   * The model file.
   */
  private final File modelFile;
  /**
   * Reads and writes models into xml files.
   */
  private final ModelParser modelParser;

  /**
   * Creates a new XMLFileModelPersister.
   *
   * @param directory The application's home directory.
   * @param modelParser Reads and writes into the xml file.
   */
  @Inject
  public XMLFileModelPersister(@ApplicationHome File directory,
                               ModelParser modelParser) {
    this.modelParser = requireNonNull(modelParser, "modelParser");
    this.dataDirectory = new File(requireNonNull(directory, "directory"), "data");

    this.modelFile = new File(dataDirectory, MODEL_FILE_NAME);
  }

  @Override
  public Optional<String> getPersistentModelName()
      throws IllegalStateException {
    if (!hasSavedModel()) {
      return Optional.empty();
    }
    return Optional.of(readXMLModelName(modelFile));
  }

  @Override
  public void saveModel(PlantModelCreationTO model)
      throws IllegalStateException {
    requireNonNull(model, "model");

    LOG.debug("Saving model '{}'.", model.getName());

    // Check if writing the model is possible.
    checkState(dataDirectory.isDirectory() || dataDirectory.mkdirs(),
               "%s is not an existing directory and could not be created, either.",
               dataDirectory.getPath());
    checkState(!modelFile.exists() || modelFile.isFile(),
               "%s exists, but is not a regular file",
               modelFile.getPath());
    try {
      if (modelFile.exists()) {
        createBackup();
      }

      modelParser.writeModel(model, modelFile);
    }
    catch (IOException exc) {
      throw new IllegalStateException("Exception saving model", exc);
    }
  }

  @Override
  public PlantModelCreationTO readModel()
      throws IllegalStateException {
    // Return empty model if there is no saved model
    if (!hasSavedModel()) {
      return new PlantModelCreationTO("empty model");
    }

    // Read the model from the file.
    return readXMLModel(modelFile);
  }

  @Override
  public boolean hasSavedModel() {
    return modelFileExists();
  }

  /**
   * Creates a backup of the currently saved model file by copying it to the
   * "backups" subdirectory.
   *
   * Assumes that the model file exists.
   *
   * @throws IOException If the backup directory is not accessible or copying
   * the file fails.
   */
  private void createBackup()
      throws IOException {
    // Generate backup file name
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss-SSS");
    String time = sdf.format(cal.getTime());
    String modelBackupName = MODEL_FILE_NAME + "_backup_" + time;
    // Make sure backup directory exists
    File modelBackupDirectory = new File(dataDirectory, "backups");
    if (modelBackupDirectory.exists()) {
      if (!modelBackupDirectory.isDirectory()) {
        throw new IOException(
            modelBackupDirectory.getPath() + " exists, but is not a directory");
      }
    }
    else {
      if (!modelBackupDirectory.mkdir()) {
        throw new IOException(
            "Could not create model directory " + modelBackupDirectory.getPath());
      }
    }
    // Backup the model file
    Files.copy(modelFile.toPath(),
               new File(modelBackupDirectory, modelBackupName).toPath());
  }

  /**
   * Test if the data directory with a model file exist. If not, throw an
   * exception.
   *
   * @throws IOException If check failed.
   */
  private boolean modelFileExists() {
    if (!modelFile.exists()) {
      return false;
    }
    if (!modelFile.isFile()) {
      return false;
    }
    return true;
  }

  @Override
  public void removeModel()
      throws IllegalStateException {
    LOG.debug("Removing model...");
    // If the model file does not exist, don't do anything
    if (!modelFileExists()) {
      return;
    }
    try {
      createBackup();
      if (!FileSystems.deleteRecursively(modelFile)) {
        throw new IOException("Cannot delete " + modelFile.getPath());
      }
    }
    catch (IOException exc) {
      throw new IllegalStateException("Exception removing model", exc);
    }
  }

  /**
   * Reads a model's name from a given InputStream.
   *
   * @param modelFile The file containing the model.
   * @throws IOException If an exception occured while loading
   */
  private String readXMLModelName(File modelFile)
      throws IllegalStateException {
    return ofNullable(emptyToNull(readXMLModel(modelFile).getName()))
        .orElse("ModelNameMissing");
  }

  /**
   * Reads a model from a given InputStream.
   *
   * @param modelFile The file containing the model.
   * @param model The model to be built.
   * @throws IOException If an exception occured while loading
   */
  private PlantModelCreationTO readXMLModel(File modelFile)
      throws IllegalStateException {
    try {
      return modelParser.readModel(modelFile);
    }
    catch (IOException exc) {
      LOG.error("Exception parsing input", exc);
      throw new IllegalStateException("Exception parsing input", exc);
    }
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/package-info.java<|end_filename|>
/**
 * Transfer object classes for domain objects.
 */
package org.opentcs.access.to;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/ObjectNameProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import java.util.function.Function;
import org.opentcs.access.to.CreationTO;

/**
 * Provides names for {@link CreationTO}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ObjectNameProvider
    extends Function<CreationTO, String> {

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/PeripheralEntry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;

/**
 * An entry for a peripheral device represented by a {@link Location}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralEntry {

  /**
   * The peripheral comm adapter factory that created this entry's comm adapter instance.
   */
  private PeripheralCommAdapterFactory commAdapterFactory = new NullPeripheralCommAdapterFactory();
  /**
   * The comm adapter instance for this entry.
   */
  private PeripheralCommAdapter commAdapter;

  /**
   * Creates a new instance.
   *
   * @param location The location representing the pripheral device.
   */
  public PeripheralEntry(@Nonnull Location location) {
    requireNonNull(location, "location");
    this.commAdapter = commAdapterFactory.getAdapterFor(location);
  }

  @Nonnull
  public PeripheralProcessModel getProcessModel() {
    return commAdapter.getProcessModel();
  }

  @Nonnull
  public TCSResourceReference<Location> getLocation() {
    return getProcessModel().getLocation();
  }

  @Nonnull
  public PeripheralCommAdapterFactory getCommAdapterFactory() {
    return commAdapterFactory;
  }

  public void setCommAdapterFactory(@Nonnull PeripheralCommAdapterFactory commAdapterFactory) {
    this.commAdapterFactory = requireNonNull(commAdapterFactory, "commAdapterFactory");
  }

  @Nonnull
  public PeripheralCommAdapter getCommAdapter() {
    return commAdapter;
  }

  public void setCommAdapter(@Nonnull PeripheralCommAdapter commAdapter) {
    this.commAdapter = requireNonNull(commAdapter, "commAdapter");
  }

  @Override
  public String toString() {
    return "PeripheralEntry{"
        + "commAdapterFactory=" + commAdapterFactory + ", "
        + "commAdapter=" + commAdapter + '}';
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/package-info.java<|end_filename|>
/**
 * Interfaces and base classes for exchangeable components of openTCS applications.
 */
package org.opentcs.components;


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/vehicles/LocalVehicleEntryPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.vehicles;

import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.TreeMap;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.ServiceCallWrapper;
import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.management.AttachmentEvent;
import org.opentcs.drivers.vehicle.management.AttachmentInformation;
import org.opentcs.drivers.vehicle.management.ProcessModelEvent;
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
import org.opentcs.util.CallWrapper;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides a pool of {@link LocalVehicleEntry}s with an entry for every {@link Vehicle} object in
 * the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LocalVehicleEntryPool
    implements EventHandler,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LocalVehicleEntryPool.class);
  /**
   * The service portal to use for kernel interactions.
   */
  private final KernelServicePortal servicePortal;
  /**
   * The call wrapper to use for service calls.
   */
  private final CallWrapper callWrapper;
  /**
   * Where this instance registers for application events.
   */
  private final EventSource eventSource;
  /**
   * The entries of this pool.
   */
  private final Map<String, LocalVehicleEntry> entries = new TreeMap<>();
  /**
   * Whether the pool is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param servicePortal The service portal to use for kernel interactions.
   * @param callWrapper The call wrapper to use for service calls.
   * @param eventSource Where this instance registers for application events.
   */
  @Inject
  public LocalVehicleEntryPool(KernelServicePortal servicePortal,
                               @ServiceCallWrapper CallWrapper callWrapper,
                               @ApplicationEventBus EventSource eventSource) {
    this.servicePortal = requireNonNull(servicePortal, "servicePortal");
    this.callWrapper = requireNonNull(callWrapper, "callWrapper");
    this.eventSource = requireNonNull(eventSource, "eventSource");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      LOG.debug("Already initialized.");
      return;
    }

    eventSource.subscribe(this);

    try {

      Set<Vehicle> vehicles = callWrapper.call(() -> servicePortal.getVehicleService().fetchObjects(Vehicle.class));
      for (Vehicle vehicle : vehicles) {
        AttachmentInformation ai
            = callWrapper.call(() -> servicePortal.getVehicleService().fetchAttachmentInformation(vehicle.getReference()));
        VehicleProcessModelTO processModel
            = callWrapper.call(() -> servicePortal.getVehicleService().fetchProcessModel(vehicle.getReference()));
        LocalVehicleEntry entry = new LocalVehicleEntry(ai, processModel);
        entries.put(vehicle.getName(), entry);
      }
    }
    catch (Exception ex) {
      LOG.warn("Error initializing local vehicle entry pool", ex);
      entries.clear();
      return;
    }

    LOG.debug("Initialized vehicle entry pool: {}", entries);
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      LOG.debug("Not initialized.");
      return;
    }

    eventSource.unsubscribe(this);

    entries.clear();
    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof ProcessModelEvent) {
      ProcessModelEvent e = (ProcessModelEvent) event;
      LocalVehicleEntry entry = getEntryFor(e.getUpdatedProcessModel().getVehicleName());
      if (entry == null) {
        return;
      }
      entry.setProcessModel(e.getUpdatedProcessModel());
    }
    else if (event instanceof AttachmentEvent) {
      AttachmentEvent e = (AttachmentEvent) event;
      LocalVehicleEntry entry = getEntryFor(e.getVehicleName());
      if (entry == null) {
        return;
      }
      entry.setAttachmentInformation(e.getUpdatedAttachmentInformation());
    }
  }

  @Nonnull
  public Map<String, LocalVehicleEntry> getEntries() {
    return entries;
  }

  @Nullable
  public LocalVehicleEntry getEntryFor(String vehicleName) {
    return vehicleName == null ? null : entries.get(vehicleName);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/transport/DefaultOrderTypeSuggestions.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import java.util.HashSet;
import java.util.Set;
import org.opentcs.components.plantoverview.OrderTypeSuggestions;
import org.opentcs.data.order.OrderConstants;

/**
 * The default suggestions for transport order types.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultOrderTypeSuggestions
    implements OrderTypeSuggestions {

  /**
   * The transport order type suggestions.
   */
  private final Set<String> typeSuggestions = new HashSet<>();

  public DefaultOrderTypeSuggestions() {
    typeSuggestions.add(OrderConstants.TYPE_NONE);
    typeSuggestions.add(OrderConstants.TYPE_CHARGE);
    typeSuggestions.add(OrderConstants.TYPE_PARK);
    typeSuggestions.add(OrderConstants.TYPE_TRANSPORT);
  }

  @Override
  public Set<String> getTypeSuggestions() {
    return typeSuggestions;
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/ContinuousLoadPanelConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the continuous load panel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(ContinuousLoadPanelConfiguration.PREFIX)
public interface ContinuousLoadPanelConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "continuousloadpanel";

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to enable to register/enable the continuous load panel.",
      orderKey = "0_enable")
  boolean enable();
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/AbstractConnection.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.components.properties.event.NullAttributesChangeListener;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.event.ConnectionChangeEvent;
import org.opentcs.guing.event.ConnectionChangeListener;
import org.opentcs.guing.model.AbstractConnectableModelComponent;
import org.opentcs.guing.model.AbstractModelComponent;
import org.opentcs.guing.model.DrawnModelComponent;
import org.opentcs.guing.model.ModelComponent;

/**
 * Abstract implementation for connections:
 * <ol>
 * <li>between two points {
 *
 * @see PathModel}</li>
 * <li>between a point and a location {@link LinkModel}</li>
 * </ol>
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractConnection
    extends AbstractModelComponent
    implements DrawnModelComponent,
               AttributesChangeListener {

  /**
   * Key for the start component.
   */
  public static final String START_COMPONENT = "startComponent";
  /**
   * Key for the end component.
   */
  public static final String END_COMPONENT = "endComponent";
  /**
   * The start component (Location or Point).
   */
  private transient ModelComponent fStartComponent;
  /**
   * The end component (Location or Point).
   */
  private transient ModelComponent fEndComponent;
  /**
   * Listeners that are interested in changes of the connected objects.
   */
  private transient List<ConnectionChangeListener> fConnectionChangeListeners
      = new LinkedList<>();

  /**
   * Creates a new instance.
   */
  public AbstractConnection() {
    // Do nada.
  }

  /**
   * Returns this connection's start component.
   *
   * @return The start component.
   */
  public ModelComponent getStartComponent() {
    return fStartComponent;
  }

  /**
   * Returns this connection's end component.
   *
   * @return The end component.
   */
  public ModelComponent getEndComponent() {
    return fEndComponent;
  }

  /**
   * Sets this connection's start and end component.
   *
   * @param startComponent The start component.
   * @param endComponent The end component.
   */
  public void setConnectedComponents(ModelComponent startComponent,
                                     ModelComponent endComponent) {
    updateListenerRegistrations(startComponent, endComponent);
    updateComponents(startComponent, endComponent);

    // TODO: Points and locations are still missing an implementation of equals().
    if (!Objects.equals(fStartComponent, startComponent)
        || !Objects.equals(fEndComponent, endComponent)) {
      fStartComponent = startComponent;
      fEndComponent = endComponent;
      connectionChanged();
    }
  }

  /**
   * Notifies this connection that it is being removed.
   */
  public void removingConnection() {
    if (fStartComponent != null) {
      fStartComponent.removeAttributesChangeListener(this);

      if (fStartComponent instanceof AbstractConnectableModelComponent) {
        ((AbstractConnectableModelComponent) fStartComponent).removeConnection(this);
      }
    }

    if (fEndComponent != null) {
      fEndComponent.removeAttributesChangeListener(this);

      if (fEndComponent instanceof AbstractConnectableModelComponent) {
        ((AbstractConnectableModelComponent) fEndComponent).removeConnection(this);
      }
    }
  }

  /**
   * Adds a listener.
   *
   * @param listener The new listener.
   */
  public void addConnectionChangeListener(ConnectionChangeListener listener) {
    if (fConnectionChangeListeners == null) {
      fConnectionChangeListeners = new LinkedList<>();
    }

    if (!fConnectionChangeListeners.contains(listener)) {
      fConnectionChangeListeners.add(listener);
    }
  }

  /**
   * Removes a listener.
   *
   * @param listener The listener to remove.
   */
  public void removeConnectionChangeListener(ConnectionChangeListener listener) {
    fConnectionChangeListeners.remove(listener);
  }

  public StringProperty getPropertyStartComponent() {
    return (StringProperty) getProperty(START_COMPONENT);
  }

  public StringProperty getPropertyEndComponent() {
    return (StringProperty) getProperty(END_COMPONENT);
  }

  @Override // AttributesChangeListener
  public void propertiesChanged(AttributesChangeEvent e) {
    if (getStartComponent().getPropertyName().hasChanged()
        || getEndComponent().getPropertyName().hasChanged()) {
      if (nameFulfillsConvention()) {
        updateName();
      }
      else {
        // Don't forget to update these properties.
        getPropertyStartComponent().setText(fStartComponent.getName());
        getPropertyEndComponent().setText(fEndComponent.getName());
      }
    }
  }

  @Override
  public AbstractConnection clone()
      throws CloneNotSupportedException {
    AbstractConnection clone = (AbstractConnection) super.clone();
    clone.fConnectionChangeListeners = new LinkedList<>();

    return clone;
  }

  /**
   * Removes the current start and end components and establishes this connection
   * between the given components.
   *
   * @param startComponent The new start component.
   * @param endComponent The new end component.
   */
  private void updateComponents(ModelComponent startComponent,
                                ModelComponent endComponent) {
    if (fStartComponent instanceof AbstractConnectableModelComponent) {
      ((AbstractConnectableModelComponent) fStartComponent).removeConnection(this);
    }

    if (fEndComponent instanceof AbstractConnectableModelComponent) {
      ((AbstractConnectableModelComponent) fEndComponent).removeConnection(this);
    }

    if (startComponent instanceof AbstractConnectableModelComponent) {
      ((AbstractConnectableModelComponent) startComponent).addConnection(this);
    }

    if (endComponent instanceof AbstractConnectableModelComponent) {
      ((AbstractConnectableModelComponent) endComponent).addConnection(this);
    }
  }

  /**
   * Informs all listener that the start and/or end component have changed.
   */
  private void connectionChanged() {
    if (fConnectionChangeListeners == null) {
      return;
    }

    for (ConnectionChangeListener listener : fConnectionChangeListeners) {
      listener.connectionChanged(new ConnectionChangeEvent(this));
    }
  }

  /**
   * Deregistrates and reregistrates itself as a listener on the
   * connected components. This is important as the name of the connection
   * is dependant on the connected components.
   *
   * @param startComponent The new start component to register with.
   * @param endComponent The new end component to register with.
   */
  private void updateListenerRegistrations(ModelComponent startComponent,
                                           ModelComponent endComponent) {
    if (fStartComponent != null) {
      fStartComponent.removeAttributesChangeListener(this);
    }

    if (fEndComponent != null) {
      fEndComponent.removeAttributesChangeListener(this);
    }

    startComponent.addAttributesChangeListener(this);
    endComponent.addAttributesChangeListener(this);
  }

  /**
   * Refreshes the name of this connection.
   */
  public void updateName() {
    StringProperty property = getPropertyName();

    if (property != null) {
      String oldName = property.getText();
      String newName = getStartComponent().getName() + " --- " + getEndComponent().getName();
      property.setText(newName);

      if (!newName.equals(oldName)) {
        property.markChanged();
      }

      propertiesChanged(new NullAttributesChangeListener());
    }
    getPropertyStartComponent().setText(fStartComponent.getName());
    getPropertyEndComponent().setText(fEndComponent.getName());
  }

  /**
   * Checks if the name of this connection follows a defined naming scheme.
   * Definition: {@literal <startComponent> --- <endComponent>}
   *
   * @return {@code true}, if the name fulfills the convention, otherwise {@code false}.
   */
  private boolean nameFulfillsConvention() {
    StringProperty property = getPropertyName();
    if (property != null) {
      String name = property.getText();
      String nameByConvention = getPropertyStartComponent().getText() + " --- "
          + getPropertyEndComponent().getText();

      if (name.equals(nameByConvention)) {
        return true;
      }
    }

    return false;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardPeripheralService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
import org.opentcs.kernel.peripherals.PeripheralAttachmentManager;
import org.opentcs.kernel.peripherals.PeripheralEntry;
import org.opentcs.kernel.peripherals.PeripheralEntryPool;
import org.opentcs.kernel.workingset.Model;

/**
 * This class is the standard implementation of the {@link PeripheralService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardPeripheralService
    extends AbstractTCSObjectService
    implements InternalPeripheralService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The attachment manager.
   */
  private final PeripheralAttachmentManager attachmentManager;
  /**
   * The pool of peripheral entries.
   */
  private final PeripheralEntryPool peripheralEntryPool;
  /**
   * The model facade to the object pool.
   */
  private final Model model;

  /**
   * Creates a new instance.
   *
   * @param objectService The tcs object service.
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param attachmentManager The attachment manager.
   * @param peripheralEntryPool The pool of peripheral entries.
   * @param model The model to be used.
   */
  @Inject
  public StandardPeripheralService(TCSObjectService objectService,
                                   @GlobalSyncObject Object globalSyncObject,
                                   PeripheralAttachmentManager attachmentManager,
                                   PeripheralEntryPool peripheralEntryPool,
                                   Model model) {
    super(objectService);
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.attachmentManager = requireNonNull(attachmentManager, "attachmentManager");
    this.peripheralEntryPool = requireNonNull(peripheralEntryPool, "peripheralEntryPool");
    this.model = requireNonNull(model, "model");
  }

  @Override
  public void attachCommAdapter(TCSResourceReference<Location> ref,
                                PeripheralCommAdapterDescription description)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      attachmentManager.attachAdapterToLocation(ref, description);
    }
  }

  @Override
  public void disableCommAdapter(TCSResourceReference<Location> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      peripheralEntryPool.getEntryFor(ref).getCommAdapter().disable();
    }
  }

  @Override
  public void enableCommAdapter(TCSResourceReference<Location> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      peripheralEntryPool.getEntryFor(ref).getCommAdapter().enable();
    }
  }

  @Override
  public PeripheralAttachmentInformation fetchAttachmentInformation(
      TCSResourceReference<Location> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      return attachmentManager.getAttachmentInformation(ref);
    }
  }

  @Override
  public PeripheralProcessModel fetchProcessModel(TCSResourceReference<Location> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      return peripheralEntryPool.getEntryFor(ref).getCommAdapter().getProcessModel();
    }
  }

  @Override
  public void sendCommAdapterCommand(TCSResourceReference<Location> ref,
                                     PeripheralAdapterCommand command)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      PeripheralEntry entry = peripheralEntryPool.getEntryFor(ref);
      synchronized (entry.getCommAdapter()) {
        entry.getCommAdapter().execute(command);
      }
    }
  }

  @Override
  public void updatePeripheralProcState(TCSResourceReference<Location> ref,
                                        PeripheralInformation.ProcState state)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setLocationProcState(ref, state);
    }
  }

  @Override
  public void updatePeripheralReservationToken(TCSResourceReference<Location> ref,
                                               String reservationToken)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setLocationReservationToken(ref, reservationToken);
    }
  }

  @Override
  public void updatePeripheralState(TCSResourceReference<Location> ref,
                                    PeripheralInformation.State state)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setLocationState(ref, state);
    }
  }

  @Override
  public void updatePeripheralJob(TCSResourceReference<Location> ref,
                                  TCSObjectReference<PeripheralJob> peripheralJob)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setLocationPeripheralJob(ref, peripheralJob);
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/guiceConfig/java/org/opentcs/strategies/basic/peripherals/dispatching/DefaultPeripheralJobDispatcherModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;

/**
 * Guice configuration for the default peripheral job dispatcher.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPeripheralJobDispatcherModule
    extends KernelInjectionModule {

  @Override
  protected void configure() {
    configureDispatcherDependencies();
    bindPeripheralJobDispatcher(DefaultPeripheralJobDispatcher.class);
  }

  private void configureDispatcherDependencies() {
    bind(DefaultPeripheralJobDispatcherConfiguration.class)
        .toInstance(getConfigBindingProvider().get(DefaultPeripheralJobDispatcherConfiguration.PREFIX,
                                                   DefaultPeripheralJobDispatcherConfiguration.class));

    bind(PeripheralJobCallback.class).to(DefaultPeripheralJobDispatcher.class);
    bind(PeripheralReleaseStrategy.class).to(DefaultPeripheralReleaseStrategy.class);
    bind(JobSelectionStrategy.class).to(DefaultJobSelectionStrategy.class);
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v002/V002ModelParser.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v002;

import java.io.IOException;
import java.io.Reader;
import java.util.Objects;

/**
 * The parser for V002 models.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V002ModelParser {

  /**
   * The file format version this parser works with.
   */
  public static final String VERSION_STRING = "0.0.2";

  /**
   * Reads a model with the given reader and parses it to a {@link V002PlantModelTO} instance.
   *
   * @param reader The reader to use.
   * @param modelVersion The model version.
   * @return The parsed {@link V002PlantModelTO}.
   * @throws IOException If there was an error reading the model.
   */
  public V002PlantModelTO readRaw(Reader reader, String modelVersion)
      throws IOException {

    if (Objects.equals(modelVersion, VERSION_STRING)) {
      return V002PlantModelTO.fromXml(reader);
    }
    else {
      throw new IllegalArgumentException(
          String.format("There is no parser for a model file with version: %s.", modelVersion)
      );
    }
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/PublishEventCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.drivers.vehicle.VehicleCommAdapterEvent;

/**
 * A command to publish {@link VehicleCommAdapterEvent}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PublishEventCommand
    implements AdapterCommand {

  /**
   * The event to publish.
   */
  private final VehicleCommAdapterEvent event;

  /**
   * Creates a new instance.
   *
   * @param event The event to publish.
   */
  public PublishEventCommand(@Nonnull VehicleCommAdapterEvent event) {
    this.event = requireNonNull(event, "event");
  }

  @Override
  public void execute(VehicleCommAdapter adapter) {
    adapter.getProcessModel().publishEvent(event);
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/gui/dialog/NullConnectionParamSet.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.gui.dialog;

/**
 * A connection param set used for not established connections.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullConnectionParamSet
    extends ConnectionParamSet {

  public NullConnectionParamSet() {
    super("-", "", 0);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/AbstractTCSObjectService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.access.CredentialsException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;

/**
 * Delegate method calls to the {@link TCSObjectService} implementation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractTCSObjectService
    implements TCSObjectService {

  /**
   * The tcs object service to delegate method calls to.
   */
  private final TCSObjectService objectService;

  /**
   * Creates a new instance.
   *
   * @param objectService The service to delegate method calls to.
   */
  public AbstractTCSObjectService(TCSObjectService objectService) {
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public <T extends TCSObject<T>> T fetchObject(Class<T> clazz, TCSObjectReference<T> ref)
      throws CredentialsException {
    return getObjectService().fetchObject(clazz, ref);
  }

  @Override
  public <T extends TCSObject<T>> T fetchObject(Class<T> clazz, String name)
      throws CredentialsException {
    return getObjectService().fetchObject(clazz, name);
  }

  @Override
  public <T extends TCSObject<T>> Set<T> fetchObjects(Class<T> clazz)
      throws CredentialsException {
    return getObjectService().fetchObjects(clazz);
  }

  @Override
  public <T extends TCSObject<T>> Set<T> fetchObjects(@Nonnull Class<T> clazz,
                                                      @Nonnull Predicate<? super T> predicate)
      throws CredentialsException {
    return getObjectService().fetchObjects(clazz, predicate);
  }

  @Override
  public void updateObjectProperty(TCSObjectReference<?> ref,
                                   String key,
                                   @Nullable String value)
      throws ObjectUnknownException, CredentialsException {
    getObjectService().updateObjectProperty(ref, key, value);
  }

  @Override
  public void appendObjectHistoryEntry(TCSObjectReference<?> ref, ObjectHistory.Entry entry)
      throws ObjectUnknownException, KernelRuntimeException {
    getObjectService().appendObjectHistoryEntry(ref, entry);
  }

  /**
   * Retruns the {@link TCSObjectService} implementation being used.
   *
   * @return The {@link TCSObjectService} implementation being used.
   */
  public TCSObjectService getObjectService() {
    return objectService;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/event/EventBus.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.event;

/**
 * A distributor of events.
 * Forwards events received via {@link #onEvent(java.lang.Object)} to all subscribed handlers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface EventBus
    extends EventHandler,
            EventSource {

}


<|start_filename|>openTCS-API-Injection/src/main/java/org/opentcs/customizations/controlcenter/package-info.java<|end_filename|>
/**
 * Components supporting extension and customization of the openTCS kernel control center
 * application.
 */
package org.opentcs.customizations.controlcenter;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/PrioritizedParkingPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeParkVehicleSelectionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Creates parking orders for idle vehicles not already at a parking position considering only
 * prioritized parking positions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PrioritizedParkingPhase
    extends AbstractParkingPhase {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PrioritizedParkingPhase.class);
  /**
   * A filter for selecting vehicles that may be parked.
   */
  private final CompositeParkVehicleSelectionFilter vehicleSelectionFilter;

  @Inject
  public PrioritizedParkingPhase(
      InternalTransportOrderService orderService,
      PrioritizedParkingPositionSupplier parkingPosSupplier,
      Router router,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      TransportOrderUtil transportOrderUtil,
      DefaultDispatcherConfiguration configuration,
      CompositeParkVehicleSelectionFilter vehicleSelectionFilter) {
    super(orderService,
          parkingPosSupplier,
          router,
          assignmentCandidateSelectionFilter,
          transportOrderUtil,
          configuration);
    this.vehicleSelectionFilter = requireNonNull(vehicleSelectionFilter, "vehicleSelectionFilter");
  }

  @Override
  public void run() {
    if (!getConfiguration().parkIdleVehicles()
        || !getConfiguration().considerParkingPositionPriorities()) {
      return;
    }

    LOG.debug("Looking for vehicles to send to prioritized parking positions...");

    getOrderService().fetchObjects(Vehicle.class).stream()
        .filter(vehicle -> vehicleSelectionFilter.apply(vehicle).isEmpty())
        .forEach(vehicle -> createParkingOrder(vehicle));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/PlantModelImporter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.io.IOException;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.opentcs.access.to.model.PlantModelCreationTO;

/**
 * Implementations provide a way to import plant model data that is read from some external source
 * or generated.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PlantModelImporter {

  /**
   * Imports (or generates) plant model data.
   *
   * @return The imported plant model data. May be empty if the user aborted the import.
   * @throws IOException If there was a problem importing plant model data.
   */
  @Nonnull
  Optional<PlantModelCreationTO> importPlantModel()
      throws IOException;

  /**
   * Returns a (localized) short textual description of this importer.
   *
   * @return A (localized) short textual description of this importer.
   */
  @Nonnull
  String getDescription();
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/TextListInputPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.List;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * An input panel with a text field for user input as well as a list of predefined
 * inputs to select from. 
 * @author <NAME> (Fraunhofer IML)
 */
public final class TextListInputPanel
    extends TextInputPanel {

  /** 
   * Creates a new instance TextListInputPanel.
   * @param title the title of the panel
   */
  private TextListInputPanel(String title) {
    super(title);
    resetable = false;
    initComponents();
    list.addListSelectionListener(new ListSelectionListener() {
      @Override
      public void valueChanged(ListSelectionEvent e) {
        if (!e.getValueIsAdjusting()) {
          Object selection = list.getSelectedValue();
          if (selection != null) {
            inputField.setText((String) selection);
          }
        }
      }
    });
  }

  @Override
  protected void captureInput() {
    input = inputField.getText();
  }

  /**
   * Enable input validation against the given regular expression. 
   * @see InputPanel#addValidationListener
   * @param format A regular expression.
   */
  private void enableInputValidation(String format) {
    if (format != null) {
      inputField.getDocument().addDocumentListener(new TextInputValidator(format));
    }
  }

  // CHECKSTYLE:OFF
  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    messageLabel = new javax.swing.JLabel();
    inputField = new javax.swing.JTextField();
    jScrollPane1 = new javax.swing.JScrollPane();
    list = new javax.swing.JList<String>();

    setLayout(new java.awt.GridBagLayout());

    messageLabel.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    messageLabel.setText("Message");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(messageLabel, gridBagConstraints);

    inputField.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    inputField.setPreferredSize(new java.awt.Dimension(70, 20));
    inputField.addFocusListener(new java.awt.event.FocusAdapter() {
      public void focusGained(java.awt.event.FocusEvent evt) {
        inputFieldFocusGained(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    add(inputField, gridBagConstraints);

    list.setFont(new java.awt.Font("Arial", 0, 11)); // NOI18N
    list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
    jScrollPane1.setViewportView(list);

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    add(jScrollPane1, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents

  private void inputFieldFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_inputFieldFocusGained
    inputField.selectAll();
  }//GEN-LAST:event_inputFieldFocusGained
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JTextField inputField;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JList<String> list;
  private javax.swing.JLabel messageLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON

  /**
   * See {@link InputPanel.Builder}.
   */
  public static class Builder
      implements InputPanel.Builder {

    /**
     * The panel's title.
     */
    private final String title;
    /**
     * The optional message.
     */
    private String message;
    /**
     * Content for the dropdown list.
     */
    private final List<String> content;
    /**
     * Regex for validation of the text field's content.
     */
    private String format;
    /**
     * Initially selected index of the list.
     * Default is 0.
     */
    private int initialIndex;

    /**
     * Create a new <code>Builder</code>.
     * @param title the title of the panel
     * @param content Predefined items to display in the panel's list
     */
    public Builder(String title, List<String> content) {
      this.title = title;
      this.content = content;
    }

    /**
     * Set the message of the panel.
     * The user of this method must take care for the line breaks in the message,
     * as it is not wrapped automatically!
     * @param message the message
     * @return the instance of this <code>Builder</code>
     */
    public Builder setMessage(String message) {
      this.message = message;
      return this;
    }

    /**
     * Make the panel validate it's input.
     * @param format The regular expression that will be used for validation.
     * @return the instance of this <code>Builder</code>
     */
    public Builder enableValidation(String format) {
      this.format = format;
      return this;
    }

    /**
     * Set the initial selected list entry.
     * @param index must be &gt; 0, will have no effect otherwise
     * @return the instance of this <code>Builder</code>
     */
    public Builder setInitialSelection(int index) {
      if (index >= 0) {
        initialIndex = index;
      }
      return this;
    }

    /**
     * Set the initial selected list entry. 
     * @param element Element to select. Selection remains unchanged if
     *                element ist not in the list or element is 
     *                <code>null</code>.
     * @return the instance fo this <code>Builder</code>
     */
    public Builder setInitialSelection(String element) {
      int index;
      try {
        index = content.indexOf(element);
      }
      catch (NullPointerException e) {
        index = -1;
      }
      return setInitialSelection(index);
    }

    @Override
    public TextListInputPanel build() {
      TextListInputPanel panel = new TextListInputPanel(title);
      panel.enableInputValidation(format);
      panel.messageLabel.setText(message);
      panel.list.setListData(content.toArray(new String[content.size()]));
      panel.list.setSelectedIndex(initialIndex);
      return panel;
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/configuration/ConfigurationBindingProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.configuration;

/**
 * A provider to get bindings (implementations) for configuration interfaces.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ConfigurationBindingProvider {

  /**
   * Returns a binding for a configuration interface.
   *
   * @param <T> The configuration interface to get an instance for.
   * @param prefix Relative path to configuration values.
   * @param type The class for {@literal <T>}.
   * @return The corresponding binding.
   */
  <T> T get(String prefix, Class<T> type);
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/trigger/OrderGenerationTrigger.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.trigger;

import org.opentcs.access.KernelRuntimeException;

/**
 * Declares the methods of transport order generation triggers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OrderGenerationTrigger {

  /**
   * Enables or disabled order generation.
   *
   * @param enabled true to enable, false to disable
   */
  void setTriggeringEnabled(boolean enabled);

  /**
   * Triggers order generation.
   *
   * @throws KernelRuntimeException In case the kernel threw an exception when
   * creating the transport orders.
   */
  void triggerOrderGeneration()
      throws KernelRuntimeException;
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/CandidateComparatorByDeadlineTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.Route.Step;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByDeadline;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorByDeadlineTest {

  private CandidateComparatorByDeadline comparator;

  @Before
  public void setUp() {
    comparator = new CandidateComparatorByDeadline();
  }

  @Test
  public void sortEarlyDeadlinesUp() {
    Instant deadline = Instant.now();
    AssignmentCandidate candidate1 = candidateWithDeadline(deadline.plusMillis(50));
    AssignmentCandidate candidate2 = candidateWithDeadline(deadline.plusMillis(200));
    AssignmentCandidate candidate3 = candidateWithDeadline(deadline.plusMillis(100));

    List<AssignmentCandidate> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate1)));
    assertThat(list.get(1), is(theInstance(candidate3)));
    assertThat(list.get(2), is(theInstance(candidate2)));
  }

  private AssignmentCandidate candidateWithDeadline(Instant time) {
    TransportOrder deadlinedOrder = new TransportOrder("Some order", new ArrayList<>())
        .withDeadline(time);
    Step dummyStep = new Route.Step(null, null, new Point("Point1"), Vehicle.Orientation.FORWARD, 1);
    Route route = new Route(Arrays.asList(dummyStep), 10);
    List<DriveOrder> driveOrders = new LinkedList<>();
    driveOrders.add(
        new DriveOrder(new DriveOrder.Destination(new Point("Point2").getReference()))
            .withRoute(route)
    );

    return new AssignmentCandidate(new Vehicle("Vehicle1"),
                                   deadlinedOrder,
                                   driveOrders);
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/ResourcePropertyViewerEditorPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import com.google.inject.Inject;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.swing.JPanel;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.type.ResourceProperty;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.gui.StringTableCellRenderer;

/**
 * UI for viewing a resource property without being able to edit the property.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ResourcePropertyViewerEditorPanel
    extends JPanel
    implements DetailsDialogContent {

  /**
   * A resource bundle.
   */
  private static final ResourceBundleUtil BUNDLE
      = ResourceBundleUtil.getBundle(I18nPlantOverview.PROPERTIES_PATH);
  /**
   * The property edited.
   */
  private ResourceProperty fProperty;

  /**
   * Creates a new instance.
   */
  @Inject
  public ResourcePropertyViewerEditorPanel() {
    initComponents();

    itemsTable.setModel(new ItemsTableModel());
    itemsTable.setDefaultRenderer(
        TCSResourceReference.class,
        new StringTableCellRenderer<TCSResourceReference<?>>(ref -> ref == null ? "" : ref.getName())
    );

    setPreferredSize(new Dimension(400, 200));
  }

  @Override
  public void setProperty(Property property) {
    fProperty = (ResourceProperty) property;

    ItemsTableModel model = (ItemsTableModel) itemsTable.getModel();

    List<List<TCSResourceReference<?>>> values = new ArrayList<>();
    for (Set<TCSResourceReference<?>> set : fProperty.getItems()) {
      List<TCSResourceReference<?>> entry = Arrays.asList(null, null, null);
      set.forEach(resource -> {
        if (resource.getReferentClass() == Path.class) {
          entry.set(0, resource);
        }
        else if (resource.getReferentClass() == Point.class) {
          entry.set(1, resource);
        }
        else if (resource.getReferentClass() == Location.class) {
          entry.set(2, resource);
        }
      });
      values.add(entry);
    }
    model.setValues(values);

  }

  @Override
  public void updateValues() {
  }

  @Override
  public String getTitle() {
    return BUNDLE.getString("resourcePropertyViewerEditorPanel.title");
  }

  @Override
  public ResourceProperty getProperty() {
    return fProperty;
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    itemsScrollPane = new javax.swing.JScrollPane();
    itemsTable = new javax.swing.JTable();
    controlPanel = new javax.swing.JPanel();

    setLayout(new java.awt.BorderLayout());

    itemsTable.setModel(new javax.swing.table.DefaultTableModel(
      new Object [][] {

      },
      new String [] {

      }
    ));
    itemsScrollPane.setViewportView(itemsTable);

    add(itemsScrollPane, java.awt.BorderLayout.CENTER);

    controlPanel.setLayout(new java.awt.GridBagLayout());
    add(controlPanel, java.awt.BorderLayout.EAST);
  }// </editor-fold>//GEN-END:initComponents

  // CHECKSTYLE:OFF
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel controlPanel;
  private javax.swing.JScrollPane itemsScrollPane;
  private javax.swing.JTable itemsTable;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON

  protected class ItemsTableModel
      extends AbstractTableModel {

    private final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
      TCSResourceReference.class,
      TCSResourceReference.class,
      TCSResourceReference.class
    };

    /**
     * The column names.
     */
    private final String[] COLUMN_NAMES = new String[]{
      BUNDLE.getString("resourcePropertyViewerEditorPanel.table_resources.column_path.headerText"),
      BUNDLE.getString("resourcePropertyViewerEditorPanel.table_resources.column_point.headerText"),
      BUNDLE.getString("resourcePropertyViewerEditorPanel.table_resources.column_location.headerText")
    };

    private final int COLUMN_PATH = 0;
    private final int COLUMN_POINT = 1;
    private final int COLUMN_LOCATION = 2;

    private List<List<TCSResourceReference<?>>> values = new LinkedList<>();

    public ItemsTableModel() {
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
      return COLUMN_CLASSES[columnIndex];
    }

    @Override
    public String getColumnName(int columnIndex) {
      return COLUMN_NAMES[columnIndex];
    }

    @Override
    public boolean isCellEditable(int row, int column) {
      return false;
    }

    @Override
    public int getRowCount() {
      return values.size();
    }

    @Override
    public int getColumnCount() {
      return COLUMN_NAMES.length;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
      if (rowIndex < 0 || rowIndex >= getRowCount()) {
        return null;
      }
      List<TCSResourceReference<?>> entry = values.get(rowIndex);
      switch (columnIndex) {
        case COLUMN_PATH:
          return entry.get(COLUMN_PATH);
        case COLUMN_POINT:
          return entry.get(COLUMN_POINT);
        case COLUMN_LOCATION:
          return entry.get(COLUMN_LOCATION);
        default:
          throw new IllegalArgumentException("Invalid column index: " + columnIndex);
      }
    }

    public void setValues(List<List<TCSResourceReference<?>>> values) {
      this.values = values;
    }
  }

}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/vehicles/CommAdapterComboBox.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.vehicles;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Objects;
import javax.swing.JComboBox;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;

/**
 * A wide combobox which sets the selected item when receiving an update event from a
 * {@link LocalVehicleEntry}.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class CommAdapterComboBox
    extends JComboBox<VehicleCommAdapterDescription>
    implements PropertyChangeListener {

  /**
   * Creates a new instance.
   */
  public CommAdapterComboBox() {
  }

  @Override
  public VehicleCommAdapterDescription getSelectedItem() {
    return (VehicleCommAdapterDescription) super.getSelectedItem();
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if (!(evt.getSource() instanceof LocalVehicleEntry)) {
      return;
    }

    LocalVehicleEntry entry = (LocalVehicleEntry) evt.getSource();
    if (Objects.equals(entry.getAttachedCommAdapterDescription(), getModel().getSelectedItem())) {
      return;
    }

    super.setSelectedItem(entry.getAttachedCommAdapterDescription());
  }

}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/components/ComponentsInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components;

import com.google.inject.AbstractModule;
import com.google.inject.PrivateModule;
import java.awt.event.MouseListener;
import javax.inject.Singleton;
import org.opentcs.guing.components.dialogs.DialogsInjectionModule;
import org.opentcs.guing.components.dockable.DockableInjectionModule;
import org.opentcs.guing.components.drawing.DrawingInjectionModule;
import org.opentcs.guing.components.layer.LayersInjectionModule;
import org.opentcs.guing.components.properties.PropertiesInjectionModule;
import org.opentcs.guing.components.tree.AbstractTreeViewPanel;
import org.opentcs.guing.components.tree.BlockMouseListener;
import org.opentcs.guing.components.tree.BlocksTreeViewManager;
import org.opentcs.guing.components.tree.BlocksTreeViewPanel;
import org.opentcs.guing.components.tree.ComponentsTreeViewManager;
import org.opentcs.guing.components.tree.ComponentsTreeViewPanel;
import org.opentcs.guing.components.tree.TreeMouseAdapter;
import org.opentcs.guing.components.tree.TreeView;
import org.opentcs.guing.components.tree.elements.TreeElementsInjectionModule;

/**
 * A Guice module for this package.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ComponentsInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {
    install(new DialogsInjectionModule());
    install(new DockableInjectionModule());
    install(new DrawingInjectionModule());
    install(new PropertiesInjectionModule());
    install(new TreeElementsInjectionModule());

    install(new ComponentsTreeViewModule());
    install(new BlocksTreeViewModule());

    install(new LayersInjectionModule());
  }

  private static class ComponentsTreeViewModule
      extends PrivateModule {

    public ComponentsTreeViewModule() {
    }

    @Override
    protected void configure() {
      // Within this (private) module, there should only be a single tree panel.
      bind(ComponentsTreeViewPanel.class)
          .in(Singleton.class);

      // Bind the tree panel annotated with the given annotation to our single
      // instance and expose only this annotated version.
      bind(AbstractTreeViewPanel.class)
          .to(ComponentsTreeViewPanel.class);
      expose(ComponentsTreeViewPanel.class);

      // Bind TreeView to the single tree panel, too.
      bind(TreeView.class)
          .to(ComponentsTreeViewPanel.class);

      // Bind and expose a single manager for the single tree view/panel.
      bind(ComponentsTreeViewManager.class)
          .in(Singleton.class);
      expose(ComponentsTreeViewManager.class);

      bind(MouseListener.class)
          .to(TreeMouseAdapter.class);
    }
  }

  private static class BlocksTreeViewModule
      extends PrivateModule {

    public BlocksTreeViewModule() {
    }

    @Override
    protected void configure() {
      // Within this (private) module, there should only be a single tree panel.
      bind(BlocksTreeViewPanel.class)
          .in(Singleton.class);

      // Bind the tree panel annotated with the given annotation to our single
      // instance and expose only this annotated version.
      bind(AbstractTreeViewPanel.class)
          .to(BlocksTreeViewPanel.class);
      expose(BlocksTreeViewPanel.class);

      // Bind TreeView to the single tree panel, too.
      bind(TreeView.class)
          .to(BlocksTreeViewPanel.class);

      // Bind and expose a single manager for the single tree view/panel.
      bind(BlocksTreeViewManager.class)
          .in(Singleton.class);
      expose(BlocksTreeViewManager.class);

      bind(MouseListener.class)
          .to(BlockMouseListener.class);
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/extensions/controlcenter/vehicles/NullVehicleCommAdapterDescription.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.controlcenter.vehicles;

import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;

/**
 * A {@link VehicleCommAdapterDescription} for no comm adapter.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullVehicleCommAdapterDescription
    extends VehicleCommAdapterDescription {

  @Override
  public String getDescription() {
    return "-";
  }

  @Override
  public boolean isSimVehicleCommAdapter() {
    return false;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/FinishWithdrawalsPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;

/**
 * Finishes withdrawals of transport orders after the vehicle has come to a halt.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FinishWithdrawalsPhase
    implements Phase {

  /**
   * The object service
   */
  private final TCSObjectService objectService;
  private final TransportOrderUtil transportOrderUtil;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public FinishWithdrawalsPhase(TCSObjectService objectService,
                                TransportOrderUtil transportOrderUtil) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    objectService.fetchObjects(Vehicle.class).stream()
        .filter(vehicle -> vehicle.hasProcState(Vehicle.ProcState.AWAITING_ORDER))
        .filter(vehicle -> hasWithdrawnTransportOrder(vehicle))
        .forEach(vehicle -> transportOrderUtil.finishAbortion(vehicle));
  }

  private boolean hasWithdrawnTransportOrder(Vehicle vehicle) {
    return objectService.fetchObject(TransportOrder.class, vehicle.getTransportOrder())
        .hasState(TransportOrder.State.WITHDRAWN);
  }

}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/ContinuousLoadPanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.access.Kernel;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.plantoverview.PluggablePanel;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import static org.opentcs.guing.plugins.panels.loadgenerator.I18nPlantOverviewPanelLoadGenerator.BUNDLE_PATH;

/**
 * Creates load generator panels.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ContinuousLoadPanelFactory
    implements PluggablePanelFactory {

  /**
   * This classe's bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * A reference to the shared portal provider.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * A provider for the actual panels.
   */
  private final Provider<ContinuousLoadPanel> panelProvider;

  /**
   * Creates a new instance.
   * 
   * @param portalProvider The application's portal provider.
   * @param panelProvider A provider for the actual panels.
   */
  @Inject
  public ContinuousLoadPanelFactory(SharedKernelServicePortalProvider portalProvider,
                                    Provider<ContinuousLoadPanel> panelProvider) {
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.panelProvider = requireNonNull(panelProvider, "panelProvider");
  }

  @Override
  public String getPanelDescription() {
    return bundle.getString("continuousLoadPanelFactory.panelDescription");
  }

  @Override
  public PluggablePanel createPanel(Kernel.State state) {
    if (!providesPanel(state)) {
      return null;
    }

    return panelProvider.get();
  }

  @Override
  public boolean providesPanel(Kernel.State state) {
    return portalProvider != null && Kernel.State.OPERATING.equals(state);
  }
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/KernelControlCenterApplication.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.common.ClientConnectionMode;
import org.opentcs.common.KernelClientApplication;
import org.opentcs.common.PortalManager;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.kernelcontrolcenter.exchange.KernelEventFetcher;
import org.opentcs.kernelcontrolcenter.util.KernelControlCenterConfiguration;
import org.opentcs.util.event.EventBus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The kernel control center application's entry point.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class KernelControlCenterApplication
    implements KernelClientApplication {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(KernelControlCenterApplication.class);
  /**
   * The instance fetching for kernel events.
   */
  private final KernelEventFetcher eventFetcher;
  /**
   * The actual kernel control center.
   */
  private final KernelControlCenter kernelControlCenter;
  /**
   * The service portal manager.
   */
  private final PortalManager portalManager;
  /**
   * The application's event bus.
   */
  private final EventBus eventBus;
  /**
   * The application's configuration.
   */
  private final KernelControlCenterConfiguration configuration;
  /**
   * Whether this application is online or not.
   */
  private ConnectionState connectionState = ConnectionState.OFFLINE;
  /**
   * Whether this application is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param eventFetcher The instance fetching for kernel events.
   * @param kernelControlCenter The actual kernel control center.
   * @param portalManager The service portal manager.
   * @param eventBus The application's event bus.
   * @param configuration The application's configuration.
   */
  @Inject
  public KernelControlCenterApplication(KernelEventFetcher eventFetcher,
                                        KernelControlCenter kernelControlCenter,
                                        PortalManager portalManager,
                                        @ApplicationEventBus EventBus eventBus,
                                        KernelControlCenterConfiguration configuration) {
    this.eventFetcher = requireNonNull(eventFetcher, "eventHub");
    this.kernelControlCenter = requireNonNull(kernelControlCenter, "kernelControlCenter");
    this.portalManager = requireNonNull(portalManager, "portalManager");
    this.eventBus = requireNonNull(eventBus, "eventBus");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    kernelControlCenter.initialize();
    eventFetcher.initialize();

    // Trigger initial connect
    online(configuration.connectAutomaticallyOnStartup());

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    // If we want to terminate but are still online, go offline first
    offline();

    eventFetcher.terminate();
    kernelControlCenter.terminate();

    initialized = false;
  }

  @Override
  public void online(boolean autoConnect) {
    if (isOnline() || isConnecting()) {
      return;
    }

    connectionState = ConnectionState.CONNECTING;
    if (portalManager.connect(toConnectionMode(autoConnect))) {
      LOG.info("Switching application state to online...");
      connectionState = ConnectionState.ONLINE;
      eventBus.onEvent(ClientConnectionMode.ONLINE);
    }
    else {
      connectionState = ConnectionState.OFFLINE;
    }
  }

  @Override
  public void offline() {
    if (!isOnline() && !isConnecting()) {
      return;
    }

    portalManager.disconnect();

    LOG.info("Switching application state to offline...");
    connectionState = ConnectionState.OFFLINE;
    eventBus.onEvent(ClientConnectionMode.OFFLINE);
  }

  @Override
  public boolean isOnline() {
    return connectionState == ConnectionState.ONLINE;
  }

  /**
   * Returns <code>true</code> if, and only if the control center is trying to establish a
   * connection to the kernel.
   *
   * @return <code>true</code> if, and only if the control center is trying to establish a
   * connection to the kernel
   */
  public boolean isConnecting() {
    return connectionState == ConnectionState.CONNECTING;
  }

  private PortalManager.ConnectionMode toConnectionMode(boolean autoConnect) {
    return autoConnect ? PortalManager.ConnectionMode.AUTO : PortalManager.ConnectionMode.MANUAL;
  }

  /**
   * An enum to display the different states of the control center application connection to the
   * kernel.
   */
  private enum ConnectionState {
    /**
     * The control center is not connected to the kernel and is not trying to.
     */
    OFFLINE,
    /**
     * The control center is currently trying to connect to the kernel.
     */
    CONNECTING,
    /**
     * The control center is connected to the kernel.
     */
    ONLINE
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/package-info.java<|end_filename|>
/**
 * Classes describing the visual attributes of a model.
 */
package org.opentcs.data.model.visualization;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/adapter/LayoutAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.stream.Collectors;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.model.VisualLayoutCreationTO;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObject;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.data.model.visualization.VisualLayout;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An adapter for VisualLayout instances.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class LayoutAdapter
    extends AbstractProcessAdapter {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LayoutAdapter.class);
  
  @Override // OpenTCSProcessAdapter
  public void updateModelProperties(TCSObject<?> tcsObject,
                                    ModelComponent modelComponent,
                                    SystemModel systemModel,
                                    TCSObjectService objectService) {
    VisualLayout layout = requireNonNull((VisualLayout) tcsObject, "tcsObject");
    LayoutModel model = (LayoutModel) modelComponent;
    
    try {
      model.getPropertyName().setText(layout.getName());
      model.getPropertyName().markChanged();
      
      model.getPropertyScaleX().setValueAndUnit(layout.getScaleX(), LengthProperty.Unit.MM);
      model.getPropertyScaleX().markChanged();
      model.getPropertyScaleY().setValueAndUnit(layout.getScaleY(), LengthProperty.Unit.MM);
      model.getPropertyScaleY().markChanged();
      
      initLayerGroups(model, layout.getLayerGroups());
      initLayers(model, layout.getLayers());
      model.getPropertyLayerWrappers().markChanged();
      
      updateMiscModelProperties(model, layout);
    }
    catch (IllegalArgumentException e) {
      LOG.warn("", e);
    }
  }
  
  @Override
  public PlantModelCreationTO storeToPlantModel(ModelComponent modelComponent,
                                                SystemModel systemModel,
                                                PlantModelCreationTO plantModel) {
    return plantModel.withVisualLayout(
        new VisualLayoutCreationTO(modelComponent.getName())
            .withScaleX(getScaleX((LayoutModel) modelComponent))
            .withScaleY(getScaleY((LayoutModel) modelComponent))
            .withProperties(getKernelProperties(modelComponent))
            .withLayers(getLayers((LayoutModel) modelComponent))
            .withLayerGroups(getLayerGroups((LayoutModel) modelComponent))
    );
  }
  
  private void initLayerGroups(LayoutModel model, Collection<LayerGroup> groups) {
    Map<Integer, LayerGroup> layerGroups = model.getPropertyLayerGroups().getValue();
    layerGroups.clear();
    for (LayerGroup group : groups) {
      layerGroups.put(group.getId(), group);
    }
  }
  
  private void initLayers(LayoutModel model, Collection<Layer> layers) {
    Map<Integer, LayerWrapper> layerWrappers = model.getPropertyLayerWrappers().getValue();
    layerWrappers.clear();
    
    Map<Integer, LayerGroup> layerGroups = model.getPropertyLayerGroups().getValue();
    for (Layer layer : layers) {
      layerWrappers.put(layer.getId(),
                        new LayerWrapper(layer, layerGroups.get(layer.getGroupId())));
    }
  }
  
  private double getScaleX(LayoutModel model) {
    return model.getPropertyScaleX().getValueByUnit(LengthProperty.Unit.MM);
  }
  
  private double getScaleY(LayoutModel model) {
    return model.getPropertyScaleY().getValueByUnit(LengthProperty.Unit.MM);
  }
  
  private List<Layer> getLayers(LayoutModel model) {
    return model.getPropertyLayerWrappers().getValue().values().stream()
        .map(wrapper -> wrapper.getLayer())
        .sorted(Comparator.comparing(layer -> layer.getId()))
        .collect(Collectors.toList());
  }
  
  private List<LayerGroup> getLayerGroups(LayoutModel model) {
    return model.getPropertyLayerGroups().getValue().values().stream()
        .sorted(Comparator.comparing(group -> group.getId()))
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/Strokes.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.BasicStroke;
import java.awt.Stroke;

/**
 * Strokes used in the drawing.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Strokes {

  /**
   * Prevents instantiation of this utility class.
   */
  private Strokes() {
  }

  /**
   * Decoration of paths, points and locations that are part of a block.
   */
  public static final Stroke BLOCK_ELEMENT = new BasicStroke(4.0f);
  /**
   * Decoration of paths that are part of a transport order.
   */
  public static final Stroke PATH_ON_ROUTE
      = new BasicStroke(6.0f,
                        BasicStroke.CAP_BUTT,
                        BasicStroke.JOIN_MITER,
                        10.0f,
                        new float[] {10.0f, 5.0f},
                        0.0f);
  /**
   * Decoration of paths that are part of a withdrawn transport order.
   */
  public static final Stroke PATH_ON_WITHDRAWN_ROUTE
      = new BasicStroke(6.0f,
                        BasicStroke.CAP_BUTT,
                        BasicStroke.JOIN_MITER,
                        10.0f,
                        new float[] {8.0f, 4.0f, 2.0f, 4.0f},
                        0.0f);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/BlockCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.awt.Color;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.Block;

/**
 * A transfer object describing a block in the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class BlockCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * This block's type.
   */
  @Nonnull
  private Block.Type type = Block.Type.SINGLE_VEHICLE_ONLY;
  /**
   * This block's member names.
   */
  @Nonnull
  private Set<String> memberNames = new HashSet<>();
  /**
   * The information regarding the grahical representation of this block.
   */
  private Layout layout = new Layout();

  /**
   * Creates a new instance.
   *
   * @param name The name of this block.
   */
  public BlockCreationTO(String name) {
    super(name);
  }

  /**
   * Creates a new block.
   *
   * @param name the name of the new block.
   * @param memberNames the names of the block's members.
   * @param properties the properties.
   */
  private BlockCreationTO(@Nonnull String name,
                          @Nonnull Map<String, String> properties,
                          @Nonnull Block.Type type,
                          @Nonnull Set<String> memberNames,
                          @Nonnull Layout layout) {
    super(name, properties);
    this.type = requireNonNull(type, "type");
    this.memberNames = requireNonNull(memberNames, "memberNames");
    this.layout = requireNonNull(layout, "layout");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new name.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public BlockCreationTO withName(@Nonnull String name) {
    return new BlockCreationTO(name,
                               getModifiableProperties(),
                               type,
                               memberNames,
                               layout);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public BlockCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new BlockCreationTO(getName(),
                               properties,
                               type,
                               memberNames,
                               layout);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public BlockCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new BlockCreationTO(getName(),
                               propertiesWith(key, value),
                               type,
                               memberNames,
                               layout);
  }

  /**
   * Returns the type of this block.
   *
   * @return The type of this block.
   */
  @Nonnull
  public Block.Type getType() {
    return type;
  }

  /**
   * Creates a copy of this object with the given type.
   *
   * @param type The new type.
   * @return A copy of this object, differing in the given type.
   */
  public BlockCreationTO withType(@Nonnull Block.Type type) {
    return new BlockCreationTO(getName(),
                               getModifiableProperties(),
                               type,
                               memberNames,
                               layout);
  }

  /**
   * Returns the names of this block's members.
   *
   * @return The names of this block's members.
   */
  @Nonnull
  public Set<String> getMemberNames() {
    return Collections.unmodifiableSet(memberNames);
  }

  /**
   * Creates a copy of this object with the given members.
   *
   * @param memberNames The names of the block's members.
   * @return A copy of this object, differing in the given value.
   */
  public BlockCreationTO withMemberNames(@Nonnull Set<String> memberNames) {
    return new BlockCreationTO(getName(),
                               getModifiableProperties(),
                               type,
                               memberNames,
                               layout);
  }

  /**
   * Returns the information regarding the grahical representation of this block.
   *
   * @return The information regarding the grahical representation of this block.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public BlockCreationTO withLayout(Layout layout) {
    return new BlockCreationTO(getName(),
                               getModifiableProperties(),
                               type,
                               memberNames,
                               layout);
  }

  @Override
  public String toString() {
    return "BlockCreationTO{"
        + "name=" + getName()
        + ", type=" + type
        + ", memberNames=" + memberNames
        + ", layout=" + layout
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Contains information regarding the grahical representation of a block.
   */
  public static class Layout
      implements Serializable {

    /**
     * The color in which block elements are to be emphasized.
     */
    private final Color color;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(Color.RED);
    }

    /**
     * Creates a new instance.
     *
     * @param color The color in which block elements are to be emphasized.
     */
    public Layout(Color color) {
      this.color = requireNonNull(color, "color");
    }

    /**
     * Returns the color in which block elements are to be emphasized.
     *
     * @return The color in which block elements are to be emphasized.
     */
    public Color getColor() {
      return color;
    }

    /**
     * Creates a copy of this object, with the given color.
     *
     * @param color The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withColor(Color color) {
      return new Layout(color);
    }

    @Override
    public String toString() {
      return "Layout{"
          + "color=" + color
          + '}';
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/AttachmentInformation.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.management;

import java.io.Serializable;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;

/**
 * Describes which communication adapter a vehicle is currently associated with and which adapters
 * are available.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AttachmentInformation
    implements Serializable {

  /**
   * The vehicle this attachment information belongs to.
   */
  private final TCSObjectReference<Vehicle> vehicleReference;
  /**
   * The list of comm adapters available to be attached to the referenced vehicle.
   */
  private final List<VehicleCommAdapterDescription> availableCommAdapters;
  /**
   * The comm adapter attached to the referenced vehicle.
   */
  private final VehicleCommAdapterDescription attachedCommAdapter;

  /**
   * Creates a new instance.
   *
   * @param vehicleReference The vehicle this attachment information belongs to.
   * @param availableCommAdapters The list of comm adapters available to be attached to the
   * referenced vehicle.
   * @param attachedCommAdapter The comm adapter attached to the referenced vehicle.
   */
  public AttachmentInformation(@Nonnull TCSObjectReference<Vehicle> vehicleReference,
                               @Nonnull List<VehicleCommAdapterDescription> availableCommAdapters,
                               @Nonnull VehicleCommAdapterDescription attachedCommAdapter) {
    this.vehicleReference = requireNonNull(vehicleReference, "vehicleReference");
    this.availableCommAdapters = requireNonNull(availableCommAdapters, "availableCommAdapters");
    this.attachedCommAdapter = requireNonNull(attachedCommAdapter, "attachedCommAdapter");
  }

  /**
   * Returns the vehicle this attachment information belongs to.
   *
   * @return The vehicle this attachment information belongs to.
   */
  @Nonnull
  public TCSObjectReference<Vehicle> getVehicleReference() {
    return vehicleReference;
  }

  /**
   * Creates a copy of this object with the given vehicle reference.
   *
   * @param vehicleReference The new vehicle reference.
   * @return A copy of this object, differing in the given vehicle reference.
   */
  public AttachmentInformation withVehicleReference(TCSObjectReference<Vehicle> vehicleReference) {
    return new AttachmentInformation(vehicleReference, availableCommAdapters, attachedCommAdapter);
  }

  /**
   * Returns the list of comm adapters available to be attached to the referenced vehicle.
   *
   * @return The list of comm adapters available to be attached to the referenced vehicle.
   */
  @Nonnull
  public List<VehicleCommAdapterDescription> getAvailableCommAdapters() {
    return availableCommAdapters;
  }

  /**
   * Creates a copy of this object with the given available comm adapters.
   *
   * @param availableCommAdapters The new available comm adapters.
   * @return A copy of this object, differing in the given available comm adapters.
   */
  public AttachmentInformation withAvailableCommAdapters(
      @Nonnull List<VehicleCommAdapterDescription> availableCommAdapters) {
    return new AttachmentInformation(vehicleReference, availableCommAdapters, attachedCommAdapter);
  }

  /**
   * Returns the comm adapter attached to the referenced vehicle.
   *
   * @return The comm adapter attached to the referenced vehicle.
   */
  @Nonnull
  public VehicleCommAdapterDescription getAttachedCommAdapter() {
    return attachedCommAdapter;
  }

  /**
   * Creates a copy of this object with the given attached comm adapter.
   *
   * @param attachedCommAdapter The new attached comm adapter.
   * @return A copy of this object, differing in the given attached comm adapter.
   */
  public AttachmentInformation withAttachedCommAdapter(
      @Nonnull VehicleCommAdapterDescription attachedCommAdapter) {
    return new AttachmentInformation(vehicleReference, availableCommAdapters, attachedCommAdapter);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/factories/NullSocketFactoryProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.factories;

import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import javax.inject.Inject;

/**
 * Provides {@code null} for both client and server socket factories.
 * By using this provider, the default client-side/server-side socket factory will be used in
 * {@link Registry} stubs.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullSocketFactoryProvider
    implements SocketFactoryProvider {

  @Inject
  public NullSocketFactoryProvider() {
  }

  @Override
  public RMIClientSocketFactory getClientSocketFactory() {
    return null;
  }

  @Override
  public RMIServerSocketFactory getServerSocketFactory() {
    return null;
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/PropertiesCollection.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.components.properties.type.AbstractProperty;
import org.opentcs.guing.components.properties.type.MultipleDifferentValues;
import org.opentcs.guing.components.properties.type.Property;

/**
 * Allows to change properties with the same name of multiple model components at the same time.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class PropertiesCollection
    extends CompositeModelComponent {

  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);

  /**
   * Creates a new instance.
   *
   * @param models The model components.
   */
  public PropertiesCollection(Collection<ModelComponent> models) {
    Objects.requireNonNull(models, "models is null");

    for (ModelComponent curModel : models) {
      add(curModel);
    }

    extractSameProperties();
  }

  /**
   * Finds the properties that can be collectively edited.
   */
  private void extractSameProperties() {
    if (getChildComponents().isEmpty()) {
      return;
    }
    ModelComponent firstModel = getChildComponents().get(0);
    Map<String, Property> properties = firstModel.getProperties();

    for (Map.Entry<String, Property> curEntry : properties.entrySet()) {
      String name = curEntry.getKey();
      Property property = curEntry.getValue();
      boolean ok = true;
      boolean differentValues = false;

      if (!property.isCollectiveEditable()) {
        ok = false;
      }

      for (int i = 1; i < getChildComponents().size(); i++) {
        ModelComponent followingModel = getChildComponents().get(i);
        if (!firstModel.getClass().equals(followingModel.getClass())) {
          return;
        }

        Property pendant = followingModel.getProperty(name);

        if (pendant == null) {
          ok = false;
          break;
        }
        else if ((!pendant.isCollectiveEditable())) {
          ok = false;
          break;
        }

        if (!(property.getComparableValue() == null && pendant.getComparableValue() == null)
            && (property.getComparableValue() != null && pendant.getComparableValue() == null
                || property.getComparableValue() == null && pendant.getComparableValue() != null
                || !property.getComparableValue().equals(pendant.getComparableValue()))) {
          differentValues = true;
        }
      }

      if (ok) {
        AbstractProperty clone = (AbstractProperty) property.clone();

        if (differentValues) {
          clone.setValue(new MultipleDifferentValues());

          clone.unmarkChanged();

          clone.setDescription(property.getDescription());
          clone.setHelptext(property.getHelptext());
          clone.setModellingEditable(property.isModellingEditable());
          clone.setOperatingEditable(property.isOperatingEditable());
          setProperty(name, clone);
        }
        else {
          // TODO: clone() Methode ?
          clone.setDescription(property.getDescription());
          clone.setHelptext(property.getHelptext());
          clone.setModellingEditable(property.isModellingEditable());
          clone.setOperatingEditable(property.isOperatingEditable());
          setProperty(name, clone);
        }
      }
    }
  }

  /**
   * Notifies the registered listeners about the changed properties.
   *
   * @param listener The listener that initiated the property change.
   */
  @Override // AbstractModelComponent
  public void propertiesChanged(AttributesChangeListener listener) {
    for (ModelComponent model : getChildComponents()) {
      copyPropertiesToModel(model);
      model.propertiesChanged(listener);
    }

    extractSameProperties();
  }

  /**
   * Copies the properties to the model component.
   *
   * @param model The model component to copy properties to.
   */
  protected void copyPropertiesToModel(ModelComponent model) {
    for (String name : getProperties().keySet()) {
      Property property = getProperty(name);
      if (property.hasChanged()) {
        Property modelProperty = model.getProperty(name);
        modelProperty.copyFrom(property);
        modelProperty.markChanged();
      }
    }
  }

  @Override // AbstractModelComponent
  public String getDescription() {
    return bundle.getString("propertiesCollection.description");
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-ResourceAllocation/src/main/java/org/opentcs/guing/plugins/panels/allocation/ResourceAllocationPanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.allocation;

import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.access.Kernel;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.plantoverview.PluggablePanel;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import static org.opentcs.guing.plugins.panels.allocation.I18nPlantOverviewPanelResourceAllocation.BUNDLE_PATH;

/**
 * Provides a {@link ResourceAllocationPanel} for the plant overview if the kernel is in operating
 * state.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class ResourceAllocationPanelFactory
    implements PluggablePanelFactory {

  /**
   * This classe's bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * The provider for the portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;

  /**
   * The provider for the panel this factory wants to create.
   */
  private final Provider<ResourceAllocationPanel> panelProvider;

  /**
   * Creates a new instance.
   *
   * @param portalProvider the provider for access to the kernel
   * @param panelProvider the provider for the panel
   */
  @Inject
  public ResourceAllocationPanelFactory(SharedKernelServicePortalProvider portalProvider,
                                        Provider<ResourceAllocationPanel> panelProvider) {
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.panelProvider = requireNonNull(panelProvider, "panelProvider");
  }

  @Override
  public boolean providesPanel(Kernel.State state) {
    return (state == Kernel.State.OPERATING);

  }

  @Override
  public String getPanelDescription() {
    return bundle.getString("resourceAllocationPanelFactory.panelDescription");
  }

  @Override
  public PluggablePanel createPanel(Kernel.State state) {
    if (state != Kernel.State.OPERATING) {
      return null;
    }
    if (portalProvider == null || !portalProvider.portalShared()) {
      return null;
    }
    return panelProvider.get();
  }

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/workingset/PeripheralJobPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.workingset;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.components.kernel.ObjectNameProvider;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A {@code PeripheralJobPool} keeps all {@code PeripheralJobs}s for an openTCS kernel and provides
 * methods to create and manipulate them.
 * <p>
 * Note that no synchronization is done inside this class. Concurrent access of instances of this
 * class must be synchronized externally.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralJobPool {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralJobPool.class);
  /**
   * The system's global object pool.
   */
  private final TCSObjectPool objectPool;
  /**
   * Provides names for peripheral jobs.
   */
  private final ObjectNameProvider objectNameProvider;

  /**
   * Creates a new instance.
   *
   * @param objectPool The object pool serving as the container for this peripheral job pool's data.
   * @param orderNameProvider Provides names for peripheral jobs.
   */
  @Inject
  public PeripheralJobPool(TCSObjectPool objectPool,
                           ObjectNameProvider orderNameProvider) {
    this.objectPool = requireNonNull(objectPool, "objectPool");
    this.objectNameProvider = requireNonNull(orderNameProvider, "orderNameProvider");
  }

  /**
   * Removes all peripheral jobs from this pool.
   */
  public void clear() {
    for (PeripheralJob job : objectPool.getObjects(PeripheralJob.class)) {
      objectPool.removeObject(job.getReference());
      objectPool.emitObjectEvent(null,
                                 job,
                                 TCSObjectEvent.Type.OBJECT_REMOVED);
    }
  }

  /**
   * Adds a new peripheral job to the pool.
   *
   * @param to The transfer object from which to create the new peripheral job.
   * @return The newly created peripheral job.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  public PeripheralJob createPeripheralJob(PeripheralJobCreationTO to)
      throws ObjectUnknownException, ObjectExistsException {
    PeripheralJob job = new PeripheralJob(nameFor(to),
                                          to.getReservationToken(),
                                          toPeripheralOperation(to.getPeripheralOperation()))
        .withRelatedVehicle(toVehicleReference(to.getRelatedVehicleName()))
        .withRelatedTransportOrder(toTransportOrderReference(to.getRelatedTransportOrderName()))
        .withProperties(to.getProperties());
    objectPool.addObject(job);
    objectPool.emitObjectEvent(job, null, TCSObjectEvent.Type.OBJECT_CREATED);
    LOG.debug("Created peripheral job {}...", job.getName());

    return job;
  }

  /**
   * Sets a peripheral jobs's state.
   *
   * @param ref A reference to the peripheral job to be modified.
   * @param newState The peripheral job's new state.
   * @return The modified peripheral job.
   * @throws ObjectUnknownException If the referenced peripheral job is not in this pool.
   */
  public PeripheralJob setPeripheralJobState(TCSObjectReference<PeripheralJob> ref,
                                             PeripheralJob.State newState)
      throws ObjectUnknownException {
    LOG.debug("Updating state of peripheral job {} to {}...", ref.getName(), newState);
    PeripheralJob job = objectPool.getObject(PeripheralJob.class, ref);
    PeripheralJob previousState = job;
    job = objectPool.replaceObject(job.withState(newState));
    objectPool.emitObjectEvent(job,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return job;
  }

  private PeripheralOperation toPeripheralOperation(PeripheralOperationCreationTO to)
      throws ObjectUnknownException {
    return new PeripheralOperation(toLocationReference(to.getLocationName()),
                                   to.getOperation(),
                                   to.getExecutionTrigger(),
                                   to.isCompletionRequired());
  }

  private TCSResourceReference<Location> toLocationReference(String locationName)
      throws ObjectUnknownException {
    Location location = objectPool.getObject(Location.class, locationName);
    return location.getReference();
  }

  private TCSObjectReference<Vehicle> toVehicleReference(String vehicleName)
      throws ObjectUnknownException {
    if (vehicleName == null) {
      return null;
    }
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleName);
    return vehicle.getReference();
  }

  private TCSObjectReference<TransportOrder> toTransportOrderReference(String transportOrderName)
      throws ObjectUnknownException {
    if (transportOrderName == null) {
      return null;
    }
    TransportOrder order = objectPool.getObject(TransportOrder.class, transportOrderName);
    return order.getReference();
  }

  @Nonnull
  private String nameFor(@Nonnull PeripheralJobCreationTO to) {
    if (to.hasIncompleteName()) {
      return objectNameProvider.apply(to);
    }
    else {
      return to.getName();
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/JobSelectionStrategy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import java.util.Collection;
import java.util.Optional;
import org.opentcs.data.model.Location;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * A strategy for selecting a peripheral job to be processed next.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface JobSelectionStrategy {

  /**
   * Selects a peripheral job to be processed next by the given location out of the given
   * collection of peripheral jobs.
   *
   * @param jobs The peripheral jobs to select from.
   * @param location The location to select a peripheral job for.
   * @return The selected peripheral job.
   */
  Optional<PeripheralJob> select(Collection<PeripheralJob> jobs, Location location);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/InternalPeripheralService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * Declares the methods the peripheral service must provide which are not accessible to remote
 * peers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface InternalPeripheralService
    extends PeripheralService {

  /**
   * Updates a peripheral's processing state.
   *
   * @param ref A reference to the location to be modified.
   * @param state The peripheral's new processing state.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  void updatePeripheralProcState(TCSResourceReference<Location> ref,
                                 PeripheralInformation.ProcState state)
      throws ObjectUnknownException;

  /**
   * Updates a peripheral's reservation token.
   *
   * @param ref A reference to the location to be modified.
   * @param reservationToken The peripheral's new reservation token.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  void updatePeripheralReservationToken(TCSResourceReference<Location> ref,
                                        String reservationToken)
      throws ObjectUnknownException;

  /**
   * Updates a peripheral's state.
   *
   * @param ref A reference to the location to be modified.
   * @param state The peripheral's new state.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  void updatePeripheralState(TCSResourceReference<Location> ref,
                             PeripheralInformation.State state)
      throws ObjectUnknownException;

  /**
   * Updates a peripheral's current peripheral job.
   *
   * @param ref A reference to the location to be modified.
   * @param peripheralJob A reference to the peripheral job the peripheral device processes.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  void updatePeripheralJob(TCSResourceReference<Location> ref,
                           TCSObjectReference<PeripheralJob> peripheralJob)
      throws ObjectUnknownException;
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/components/drawing/OpenTCSDrawingViewModeling.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 *
 * Extended by IML: 1. Show Blocks and Pathes as overlay 2. Switch labels on/off
 *
 * @(#)DefaultDrawingView.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.components.drawing;

import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.jhotdraw.draw.DefaultDrawingView;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.components.drawing.BlockChangeHandler;
import org.opentcs.guing.components.drawing.DeleteEdit;
import org.opentcs.guing.components.drawing.PasteEdit;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.drawing.course.OriginChangeListener;
import org.opentcs.guing.components.drawing.figures.FigureConstants;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.drawing.figures.ModelBasedFigure;
import org.opentcs.guing.components.drawing.figures.OriginFigure;
import org.opentcs.guing.components.layer.ActiveLayerProvider;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.FigureCloner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A DrawingView implementation for the openTCS plant overview.
 *
 */
public class OpenTCSDrawingViewModeling
    extends AbstractOpenTCSDrawingView {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(OpenTCSDrawingViewModeling.class);
  /**
   * A helper for cloning figures.
   */
  private final FigureCloner figureCloner;
  /**
   * The active layer provider.
   */
  private final ActiveLayerProvider activeLayerProvider;
  /**
   * Contains figures currently in the buffer (eg when copying or cutting figures).
   */
  private List<Figure> bufferedFigures = new ArrayList<>();
  /**
   * Handles events for blocks.
   */
  private final BlockChangeHandler blockChangeHandler;

  /**
   * Creates new instance.
   *
   * @param appState Stores the application's current state.
   * @param modelManager Provides the current system model.
   * @param figureCloner A helper for cloning figures.
   * @param activeLayerProvider The active layer provider.
   * @param blockChangeHandler The handler for block changes.
   */
  @Inject
  public OpenTCSDrawingViewModeling(ApplicationState appState,
                                    ModelManager modelManager,
                                    FigureCloner figureCloner,
                                    ActiveLayerProvider activeLayerProvider,
                                    BlockChangeHandler blockChangeHandler) {
    super(appState, modelManager);
    this.figureCloner = requireNonNull(figureCloner, "figureCloner");
    this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");
    this.blockChangeHandler = requireNonNull(blockChangeHandler, "blockChangeHandler");
  }

  @Override
  public void cutSelectedItems() {
    deleteSelectedFigures();
  }

  @Override
  public void copySelectedItems() {
    bufferedFigures = getDrawing().sort(getSelectedFigures());
  }

  @Override
  public void pasteBufferedItems() {
    clearSelection();

    List<Figure> pastedFigures = new ArrayList<>();
    if (getDrawing().getChildren().containsAll(bufferedFigures)) {
      pastedFigures.addAll(copyPasteBufferedItems());
    }
    else if (Collections.disjoint(getDrawing().getChildren(), bufferedFigures)) {
      pastedFigures.addAll(cutPasteBufferedItems());
    }
    else {
      // The list of buffered figures contains a mix of figures contained in the drawing and 
      // figures not contained in the drawing. This should never happen.
      throw new IllegalStateException("Some figures to be pasted are already in the drawing, some "
          + "are not.");
    }

    placeFiguresOnActiveLayer(pastedFigures);
  }

  @Override
  public void delete() {
    deleteSelectedFigures();

    if (!bufferedFigures.isEmpty()) {
      getDrawing().fireUndoableEditHappened(new DeleteEdit(this, bufferedFigures));
    }
  }

  @Override
  public void duplicate() {
    copySelectedItems();
    pasteBufferedItems();
  }

  @Override
  public void displayDriveOrders(VehicleModel vehicle, boolean visible) {
    // Displaying drive orders is specific to operating mode
  }

  @Override
  public void followVehicle(@Nonnull final VehicleModel model) {
    // Follwing a vehicle is not possible in modeling mode
  }

  @Override
  public void stopFollowVehicle() {
    // Follwing a vehicle is not possible in modeling mode
  }

  @Override
  protected void drawTool(Graphics2D g2d) {
    super.drawTool(g2d);

    if (getEditor() == null || getEditor().getTool() == null || getEditor().getActiveView() != this) {
      return;
    }

    // Set focus on the selected figure
    highlightFocus(g2d);
  }

  @Override
  protected DefaultDrawingView.EventHandler createEventHandler() {
    return new ExtendedEventHandler();
  }

  @Override
  public void delete(Set<ModelComponent> components) {
    List<Figure> figuresToDelete = components.stream()
        .map(component -> getModelManager().getModel().getFigure(component))
        .collect(Collectors.toList());
    deleteFigures(figuresToDelete);
  }

  @Override
  public void setBlocks(ModelComponent blocks) {
    synchronized (this) {
      for (ModelComponent blockComp : blocks.getChildComponents()) {
        BlockModel block = (BlockModel) blockComp;
        block.addBlockChangeListener(blockChangeHandler);
      }
    }
  }

  /**
   * Message of the application that a block area was created.
   *
   * @param block The newly created block.
   */
  public void blockAdded(BlockModel block) {
    block.addBlockChangeListener(blockChangeHandler);
  }

  /**
   * Pastes the list of buffered figures by cloning them and adding the clones to the drawing.
   *
   * @return The list of pasted figures. (The cloned figures.)
   */
  private List<Figure> copyPasteBufferedItems() {
    // Create clones of all buffered figures
    List<Figure> clonedFigures = figureCloner.cloneFigures(bufferedFigures);
    addToSelection(clonedFigures);
    getDrawing().fireUndoableEditHappened(new PasteEdit(this, clonedFigures));

    return clonedFigures;
  }

  /**
   * Pastes the list of buffered figures by adding them to the drawing.
   *
   * @return The list of pasted figures. (The buffered figures.)
   */
  private List<Figure> cutPasteBufferedItems() {
    for (Figure deletedFigure : bufferedFigures) {
      getDrawing().add(deletedFigure);
    }
    getDrawing().fireUndoableEditHappened(new PasteEdit(this, bufferedFigures));

    return bufferedFigures;
  }

  private void placeFiguresOnActiveLayer(List<Figure> figures) {
    for (Figure figure : figures) {
      if (figure instanceof ModelBasedFigure) {
        ((ModelBasedFigure) figure).getModel()
            .getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
      }
      else if (figure instanceof LabeledFigure) {
        ((LabeledFigure) figure).getPresentationFigure().getModel()
            .getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
      }
    }
  }

  private void deleteSelectedFigures() {
    final List<Figure> deletedFigures = getDrawing().sort(getSelectedFigures());
    deleteFigures(deletedFigures);
  }

  private void deleteFigures(List<Figure> figures) {
    // Abort, if not all of the selected figures may be removed from the drawing
    for (Figure figure : figures) {
      if (!figure.isRemovable()) {
        LOG.warn("Figure is not removable: {}. Aborting.", figure);
        return;
      }
    }

    bufferedFigures = figures;
    clearSelection();

    for (Figure figure : figures) {
      if (figure instanceof OriginChangeListener) {
        Origin ref = figure.get(FigureConstants.ORIGIN);

        if (ref != null) {
          ref.removeListener((OriginChangeListener) figure);
          figure.set(FigureConstants.ORIGIN, null);
        }
      }

      getDrawing().remove(figure);
    }
  }

  private class ExtendedEventHandler
      extends AbstractExtendedEventHandler {

    @Override
    protected boolean shouldShowFigure(Figure figure) {
      return !(figure instanceof OriginFigure);
    }
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/LocationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "xPosition", "yPosition", "zPosition", "links", "locked",
                      "properties", "locationLayout"})
public class LocationTO
    extends PlantModelElementTO {

  private Long xPosition = 0L;
  private Long yPosition = 0L;
  private Long zPosition = 0L;
  private String type = "";
  private List<Link> links = new ArrayList<>();
  private Boolean locked = false;
  private LocationLayout locationLayout = new LocationLayout();

  @XmlAttribute
  public Long getxPosition() {
    return xPosition;
  }

  public LocationTO setxPosition(@Nonnull Long xPosition) {
    requireNonNull(xPosition, "xPosition");
    this.xPosition = xPosition;
    return this;
  }

  @XmlAttribute
  public Long getyPosition() {
    return yPosition;
  }

  public LocationTO setyPosition(@Nonnull Long yPosition) {
    requireNonNull(yPosition, "yPosition");
    this.yPosition = yPosition;
    return this;
  }

  @XmlAttribute
  public Long getzPosition() {
    return zPosition;
  }

  public LocationTO setzPosition(@Nonnull Long zPosition) {
    requireNonNull(zPosition, "zPosition");
    this.zPosition = zPosition;
    return this;
  }

  @XmlAttribute
  public String getType() {
    return type;
  }

  public LocationTO setType(@Nonnull String type) {
    requireNonNull(type, "type");
    this.type = type;
    return this;
  }

  @XmlElement(name = "link", required = true)
  public List<Link> getLinks() {
    return links;
  }

  public LocationTO setLinks(@Nonnull List<Link> links) {
    requireNonNull(links, "links");
    this.links = links;
    return this;
  }

  @XmlAttribute(required = true)
  public Boolean isLocked() {
    return locked;
  }

  public LocationTO setLocked(Boolean locked) {
    this.locked = locked;
    return this;
  }

  @XmlElement(required = true)
  public LocationLayout getLocationLayout() {
    return locationLayout;
  }

  public LocationTO setLocationLayout(@Nonnull LocationLayout locationLayout) {
    this.locationLayout = requireNonNull(locationLayout, "locationLayout");
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"point", "allowedOperations"})
  public static class Link {

    private String point = "";
    private List<AllowedOperationTO> allowedOperations = new ArrayList<>();

    @XmlAttribute(required = true)
    public String getPoint() {
      return point;
    }

    public Link setPoint(@Nonnull String point) {
      requireNonNull(point, "point");
      this.point = point;
      return this;
    }

    @XmlElement(name = "allowedOperation")
    public List<AllowedOperationTO> getAllowedOperations() {
      return allowedOperations;
    }

    public Link setAllowedOperations(@Nonnull List<AllowedOperationTO> allowedOperations) {
      requireNonNull(allowedOperations, "allowedOperations");
      this.allowedOperations = allowedOperations;
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"xPosition", "yPosition", "xLabelOffset", "yLabelOffset",
                        "locationRepresentation", "layerId"})
  public static class LocationLayout {

    private Long xPosition = 0L;
    private Long yPosition = 0L;
    private Long xLabelOffset = 0L;
    private Long yLabelOffset = 0L;
    private String locationRepresentation = "";
    private Integer layerId = 0;

    @XmlAttribute(required = true)
    public Long getxPosition() {
      return xPosition;
    }

    public LocationLayout setxPosition(Long xPosition) {
      this.xPosition = requireNonNull(xPosition, "xPosition");
      return this;
    }

    @XmlAttribute(required = true)
    public Long getyPosition() {
      return yPosition;
    }

    public LocationLayout setyPosition(Long yPosition) {
      this.yPosition = requireNonNull(yPosition, "yPosition");
      return this;
    }

    @XmlAttribute(required = true)
    public Long getxLabelOffset() {
      return xLabelOffset;
    }

    public LocationLayout setxLabelOffset(Long xLabelOffset) {
      this.xLabelOffset = requireNonNull(xLabelOffset, "xLabelOffset");
      return this;
    }

    @XmlAttribute(required = true)
    public Long getyLabelOffset() {
      return yLabelOffset;
    }

    public LocationLayout setyLabelOffset(Long yLabelOffset) {
      this.yLabelOffset = requireNonNull(yLabelOffset, "yLabelOffset");
      return this;
    }

    @XmlAttribute(required = true)
    public String getLocationRepresentation() {
      return locationRepresentation;
    }

    public LocationLayout setLocationRepresentation(String locationRepresentation) {
      this.locationRepresentation = requireNonNull(locationRepresentation, "locationRepresentation");
      return this;
    }

    @XmlAttribute(required = true)
    public Integer getLayerId() {
      return layerId;
    }

    public LocationLayout setLayerId(Integer layerId) {
      this.layerId = requireNonNull(layerId, "layerId");
      return this;
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/FullDispatchTask.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.strategies.basic.dispatching.phase.AssignReservedOrdersPhase;
import org.opentcs.strategies.basic.dispatching.phase.AssignSequenceSuccessorsPhase;
import org.opentcs.strategies.basic.dispatching.phase.CheckNewOrdersPhase;
import org.opentcs.strategies.basic.dispatching.phase.FinishWithdrawalsPhase;
import org.opentcs.strategies.basic.dispatching.phase.assignment.AssignFreeOrdersPhase;
import org.opentcs.strategies.basic.dispatching.phase.assignment.AssignNextDriveOrdersPhase;
import org.opentcs.strategies.basic.dispatching.phase.parking.ParkIdleVehiclesPhase;
import org.opentcs.strategies.basic.dispatching.phase.parking.PrioritizedParkingPhase;
import org.opentcs.strategies.basic.dispatching.phase.parking.PrioritizedReparkPhase;
import org.opentcs.strategies.basic.dispatching.phase.recharging.RechargeIdleVehiclesPhase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Performs a full dispatch run.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FullDispatchTask
    implements Runnable,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(FullDispatchTask.class);

  private final CheckNewOrdersPhase checkNewOrdersPhase;
  private final FinishWithdrawalsPhase finishWithdrawalsPhase;
  private final AssignNextDriveOrdersPhase assignNextDriveOrdersPhase;
  private final AssignReservedOrdersPhase assignReservedOrdersPhase;
  private final AssignSequenceSuccessorsPhase assignSequenceSuccessorsPhase;
  private final AssignFreeOrdersPhase assignFreeOrdersPhase;
  private final RechargeIdleVehiclesPhase rechargeIdleVehiclesPhase;
  private final PrioritizedReparkPhase prioritizedReparkPhase;
  private final PrioritizedParkingPhase prioritizedParkingPhase;
  private final ParkIdleVehiclesPhase parkIdleVehiclesPhase;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  @Inject
  public FullDispatchTask(CheckNewOrdersPhase checkNewOrdersPhase,
                          FinishWithdrawalsPhase finishWithdrawalsPhase,
                          AssignNextDriveOrdersPhase assignNextDriveOrdersPhase,
                          AssignReservedOrdersPhase assignReservedOrdersPhase,
                          AssignSequenceSuccessorsPhase assignSequenceSuccessorsPhase,
                          AssignFreeOrdersPhase assignFreeOrdersPhase,
                          RechargeIdleVehiclesPhase rechargeIdleVehiclesPhase,
                          PrioritizedReparkPhase prioritizedReparkPhase,
                          PrioritizedParkingPhase prioritizedParkingPhase,
                          ParkIdleVehiclesPhase parkIdleVehiclesPhase) {
    this.checkNewOrdersPhase = requireNonNull(checkNewOrdersPhase, "checkNewOrdersPhase");
    this.finishWithdrawalsPhase = requireNonNull(finishWithdrawalsPhase, "finishWithdrawalsPhase");
    this.assignNextDriveOrdersPhase = requireNonNull(assignNextDriveOrdersPhase,
                                                     "assignNextDriveOrdersPhase");
    this.assignReservedOrdersPhase = requireNonNull(assignReservedOrdersPhase,
                                                    "assignReservedOrdersPhase");
    this.assignSequenceSuccessorsPhase = requireNonNull(assignSequenceSuccessorsPhase,
                                                        "assignSequenceSuccessorsPhase");
    this.assignFreeOrdersPhase = requireNonNull(assignFreeOrdersPhase, "assignFreeOrdersPhase");
    this.rechargeIdleVehiclesPhase = requireNonNull(rechargeIdleVehiclesPhase,
                                                    "rechargeIdleVehiclesPhase");
    this.prioritizedReparkPhase = requireNonNull(prioritizedReparkPhase, "prioritizedReparkPhase");
    this.prioritizedParkingPhase = requireNonNull(prioritizedParkingPhase,
                                                  "prioritizedParkingPhase");
    this.parkIdleVehiclesPhase = requireNonNull(parkIdleVehiclesPhase, "parkIdleVehiclesPhase");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    checkNewOrdersPhase.initialize();
    finishWithdrawalsPhase.initialize();
    assignNextDriveOrdersPhase.initialize();
    assignReservedOrdersPhase.initialize();
    assignSequenceSuccessorsPhase.initialize();
    assignFreeOrdersPhase.initialize();
    rechargeIdleVehiclesPhase.initialize();
    prioritizedReparkPhase.initialize();
    prioritizedParkingPhase.initialize();
    parkIdleVehiclesPhase.initialize();

    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    checkNewOrdersPhase.terminate();
    finishWithdrawalsPhase.terminate();
    assignNextDriveOrdersPhase.terminate();
    assignReservedOrdersPhase.terminate();
    assignSequenceSuccessorsPhase.terminate();
    assignFreeOrdersPhase.terminate();
    rechargeIdleVehiclesPhase.terminate();
    prioritizedReparkPhase.terminate();
    prioritizedParkingPhase.terminate();
    parkIdleVehiclesPhase.terminate();

    initialized = false;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public final void run() {
    LOG.debug("Starting full dispatch run...");

    checkNewOrdersPhase.run();
    // Check what vehicles involved in a process should do.
    finishWithdrawalsPhase.run();
    assignNextDriveOrdersPhase.run();
    assignSequenceSuccessorsPhase.run();
    // Check what vehicles not already in a process should do.
    assignOrders();
    rechargeVehicles();
    parkVehicles();

    LOG.debug("Finished full dispatch run.");
  }

  /**
   * Assignment of orders to vehicles.
   * <p>
   * Default: Assigns reserved and then free orders to vehicles.
   * </p>
   */
  protected void assignOrders() {
    assignReservedOrdersPhase.run();
    assignFreeOrdersPhase.run();
  }

  /**
   * Recharging of vehicles.
   * <p>
   * Default: Sends idle vehicles with a degraded energy level to recharge locations.
   * </p>
   */
  protected void rechargeVehicles() {
    rechargeIdleVehiclesPhase.run();
  }

  /**
   * Parking of vehicles.
   * <p>
   * Default: Sends idle vehicles to parking positions.
   * </p>
   */
  protected void parkVehicles() {
    prioritizedReparkPhase.run();
    prioritizedParkingPhase.run();
    parkIdleVehiclesPhase.run();
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/layer/LayersPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.awt.BorderLayout;
import java.util.Arrays;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.TableRowSorter;
import org.opentcs.guing.persistence.ModelManager;

/**
 * A panel to display and edit layers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayersPanel
    extends JPanel {

  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer manager.
   */
  private final LayerManager layerManager;
  /**
   * The layer group manager.
   */
  private final LayerGroupManager layerGroupManager;
  /**
   * The layer editor.
   */
  private final LayerEditor layerEditor;
  /**
   * The table to display available layers.
   */
  private JTable table;
  /**
   * The table model.
   */
  private LayersTableModel tableModel;

  @Inject
  public LayersPanel(ModelManager modelManager,
                     LayerManager layerManager,
                     LayerGroupManager layerGroupManager,
                     LayerEditor layerEditor) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerManager = requireNonNull(layerManager, "layerManager");
    this.layerGroupManager = requireNonNull(layerGroupManager, "layerGroupManager");
    this.layerEditor = requireNonNull(layerEditor, "layerEditor");

    initComponents();
  }

  private void initComponents() {
    setLayout(new BorderLayout());

    tableModel = new LayersTableModel(modelManager, layerEditor);
    layerManager.setLayerChangeListener(tableModel);
    layerGroupManager.addLayerGroupChangeListener(tableModel);
    table = new JTable(tableModel);
    initTable();

    JScrollPane scrollPane = new JScrollPane(table);
    add(scrollPane, BorderLayout.CENTER);
  }

  private void initTable() {
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    TableRowSorter<LayersTableModel> sorter = new TableRowSorter<>(tableModel);
    // Sort the table by the layer ordinals...
    sorter.setSortKeys(Arrays.asList(
        new RowSorter.SortKey(LayersTableModel.COLUMN_ORDINAL, SortOrder.DESCENDING)
    ));
    // ...but prevent manual sorting.
    for (int i = 0; i < table.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    table.setRowSorter(sorter);

    // Hide the column that shows the layer ordinals.
    table.removeColumn(table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_ORDINAL)));

    table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_GROUP))
        .setCellRenderer(new LayerGroupCellRenderer());
    table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayersTableModel.COLUMN_GROUP_VISIBLE))
        .setCellRenderer(new DisabledCheckBoxCellRenderer());
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/AttributesTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.components.properties.type.ModelAttribute;

/**
 * A table model for the PropertiesTable.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class AttributesTableModel
    extends javax.swing.table.DefaultTableModel {

  /**
   * Stores the application's current state.
   */
  private final ApplicationState appState;

  /**
   * Creates a new instance of AttributesTableModel
   *
   * @param appState Stores the application's current state.
   */
  @Inject
  public AttributesTableModel(ApplicationState appState) {
    this.appState = requireNonNull(appState, "appState");
  }

  /**
   * Indicates whether a cell is editable.
   *
   * @param row The row of the cell to test.
   * @param col The column of the cell to test.
   * @return True if the specified cell is editable.
   */
  @Override // AbstractTableModel
  public boolean isCellEditable(int row, int col) {
    if (col == 0) {
      return false;
    }
    else { // col == 1
      ModelAttribute attribute = (ModelAttribute) getValueAt(row, col);

      if (appState.hasOperationMode(OperationMode.MODELLING)) {
        return attribute.isModellingEditable();
      }

      return attribute.isOperatingEditable();
    }
  }

  @Override  // AbstractTableModel
  public void fireTableDataChanged() {
    super.fireTableDataChanged();
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/OrderFilterResult.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import org.opentcs.data.order.TransportOrder;

/**
 * The result of a transport order filter operation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderFilterResult {

  private final TransportOrder order;

  private final Collection<String> filterReasons;

  public OrderFilterResult(TransportOrder order, Collection<String> filterReasons) {
    this.order = requireNonNull(order, "order");
    this.filterReasons = requireNonNull(filterReasons, "filterReasons");
  }

  public TransportOrder getOrder() {
    return order;
  }

  public Collection<String> getFilterReasons() {
    return filterReasons;
  }

  public boolean isFiltered() {
    return !filterReasons.isEmpty();
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/LocationTypeTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name",
                      "locationNamePrefix",
                      "allowedOperations",
                      "allowedPeripheralOperations",
                      "properties",
                      "locationTypeLayout"})
public class LocationTypeTO
    extends PlantModelElementTO {

  private String locationNamePrefix;
  private List<AllowedOperationTO> allowedOperations = new ArrayList<>();
  private List<AllowedPeripheralOperationTO> allowedPeripheralOperations = new ArrayList<>();
  private LocationTypeLayout locationTypeLayout = new LocationTypeLayout();

  @XmlAttribute
  public String getLocationNamePrefix() {
    return locationNamePrefix;
  }

  public LocationTypeTO setLocationNamePrefix(String locationNamePrefix) {
    this.locationNamePrefix = locationNamePrefix;
    return this;
  }

  @XmlElement(name = "allowedOperation")
  public List<AllowedOperationTO> getAllowedOperations() {
    return allowedOperations;
  }

  public LocationTypeTO setAllowedOperations(@Nonnull List<AllowedOperationTO> allowedOperations) {
    this.allowedOperations = requireNonNull(allowedOperations, "allowedOperations");
    return this;
  }

  @XmlElement(name = "allowedPeripheralOperation")
  public List<AllowedPeripheralOperationTO> getAllowedPeripheralOperations() {
    return allowedPeripheralOperations;
  }

  public LocationTypeTO setAllowedPeripheralOperations(
      List<AllowedPeripheralOperationTO> allowedPeripheralOperations) {
    this.allowedPeripheralOperations = requireNonNull(allowedPeripheralOperations,
                                                      "allowedPeripheralOperations");
    return this;
  }

  @XmlElement(required = true)
  public LocationTypeLayout getLocationTypeLayout() {
    return locationTypeLayout;
  }

  public LocationTypeTO setLocationTypeLayout(@Nonnull LocationTypeLayout locationTypeLayout) {
    this.locationTypeLayout = requireNonNull(locationTypeLayout, "locationTypeLayout");
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  public static class LocationTypeLayout {

    private String locationRepresentation = "";

    @XmlAttribute(required = true)
    public String getLocationRepresentation() {
      return locationRepresentation;
    }

    public LocationTypeLayout setLocationRepresentation(@Nonnull String locationRepresentation) {
      this.locationRepresentation = requireNonNull(locationRepresentation, "locationRepresentation");
      return this;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/ViewManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import bibliothek.gui.dock.common.DefaultSingleCDockable;
import java.util.List;
import java.util.Map;
import org.opentcs.guing.components.drawing.DrawingViewScrollPane;

/**
 * Manages the mapping of dockables to drawing views, transport order views and
 * order sequence views.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface ViewManager {

  Map<DefaultSingleCDockable, DrawingViewScrollPane> getDrawingViewMap();

  /**
   * Returns the title texts of all drawing views.
   *
   * @return List of strings containing the names.
   */
  List<String> getDrawingViewNames();

  /**
   * Forgets the given dockable.
   *
   * @param dockable The dockable.
   */
  void removeDockable(DefaultSingleCDockable dockable);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/jgrapht/ShortestPathConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.jgrapht;

import java.util.List;
import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the shortest path algorithm.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(ShortestPathConfiguration.PREFIX)
public interface ShortestPathConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "defaultrouter.shortestpath";

  @ConfigurationEntry(
      type = "String",
      description = {
        "The routing algorithm to be used. Valid values:",
        "'DIJKSTRA': Routes are computed using Dijkstra's algorithm.",
        "'BELLMAN_FORD': Routes are computed using the Bellman-Ford algorithm.",
        "'FLOYD_WARSHALL': Routes are computed using the Floyd-Warshall algorithm."})
  Algorithm algorithm();

  @ConfigurationEntry(
      type = "Comma-separated list of strings",
      description = {
        "The types of route evaluators/cost factors to be used.",
        "Results of multiple evaluators are added up. Valid values:",
        "'DISTANCE': A route's cost equals the sum of the lengths of its paths.",
        "'TRAVELTIME': A route's cost equals the vehicle's expected travel time.",
        "'EXPLICIT_PROPERTIES': A route's cost equals the sum of the explicitly given costs "
        + "extracted from path properties.",
        "'HOPS': A route's cost equals the number of paths it consists of."
      })
  List<String> edgeEvaluators();

  enum Algorithm {
    DIJKSTRA(false),
    BELLMAN_FORD(true),
    FLOYD_WARSHALL(false);

    private final boolean handlingNegativeCosts;

    private Algorithm(boolean handlingNegativeCosts) {
      this.handlingNegativeCosts = handlingNegativeCosts;
    }

    public boolean isHandlingNegativeCosts() {
      return handlingNegativeCosts;
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/NotificationService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.notification.UserNotification;

/**
 * Provides methods concerning {@link UserNotification}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface NotificationService {

  /**
   * Returns a list of user notifications.
   *
   * @param predicate A filter predicate that accepts the user notifications to be returned. May be
   * {@code null} to return all existing user notifications.
   * @return A list of user notifications.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  List<UserNotification> fetchUserNotifications(Predicate<UserNotification> predicate)
      throws KernelRuntimeException;

  /**
   * Publishes a user notification.
   *
   * @param notification The notification to be published.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void publishUserNotification(UserNotification notification)
      throws KernelRuntimeException;
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/action/ToolButtonListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action;

import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Objects;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.tool.Tool;

/**
 * A listener if a tool was (de)selected.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
final class ToolButtonListener
    implements ItemListener {

  private final Tool tool;
  private final DrawingEditor editor;

  /**
   * Creates a new instance.
   *
   * @param tool The tool
   * @param editor The drawing editor
   */
  public ToolButtonListener(Tool tool, DrawingEditor editor) {
    this.tool = Objects.requireNonNull(tool, "tool is null");
    this.editor = Objects.requireNonNull(editor, "editor is null");
  }

  @Override
  public void itemStateChanged(ItemEvent evt) {
    if (evt.getStateChange() == ItemEvent.SELECTED) {
      editor.setTool(tool);
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/recharging/DefaultRechargePositionSupplierTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.recharging;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import org.junit.*;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder.Destination;

/**
 * Tests for {@link DefaultRechargePositionSupplier}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultRechargePositionSupplierTest {

  /**
   * The plant model service used by the recharge strategy.
   */
  private InternalPlantModelService plantModelService;
  /**
   * The router used by the recharge strategy.
   */
  private Router router;
  /**
   * The supplier instance to be tested.
   */
  private DefaultRechargePositionSupplier rechargePosSupplier;

  @Before
  public void setUp() {
    plantModelService = mock(InternalPlantModelService.class);
    router = mock(Router.class);
    rechargePosSupplier = new DefaultRechargePositionSupplier(plantModelService, router);
  }

  @After
  public void tearDown() {
    rechargePosSupplier.terminate();
  }

  @Test
  public void findExistingRechargePosition() {
    Point currentVehiclePoint = new Point("Current vehicle point")
        .withType(Point.Type.HALT_POSITION);
    Vehicle vehicle = new Vehicle("Some vehicle")
        .withRechargeOperation("Do some recharging")
        .withCurrentPosition(currentVehiclePoint.getReference());

    Point locationAccessPoint = new Point("Location access point")
        .withType(Point.Type.HALT_POSITION);

    LocationType rechargeLocType = new LocationType("Recharge location type")
        .withAllowedOperations(Collections.singletonList(vehicle.getRechargeOperation()));
    Location location = new Location("Recharge location", rechargeLocType.getReference());

    Location.Link link = new Location.Link(location.getReference(),
                                           locationAccessPoint.getReference());
    location = location.withAttachedLinks(new HashSet<>(Arrays.asList(link)));

    locationAccessPoint = locationAccessPoint.withAttachedLinks(new HashSet<>(Arrays.asList(link)));

    when(plantModelService.fetchObjects(Location.class))
        .thenReturn(Collections.singleton(location));
    when(plantModelService.fetchObject(LocationType.class, rechargeLocType.getReference()))
        .thenReturn(rechargeLocType);
    when(plantModelService.fetchObject(Point.class, currentVehiclePoint.getReference()))
        .thenReturn(currentVehiclePoint);
    when(plantModelService.fetchObject(Point.class, locationAccessPoint.getReference()))
        .thenReturn(locationAccessPoint);

    rechargePosSupplier.initialize();

    List<Destination> result = rechargePosSupplier.findRechargeSequence(vehicle);
    assertNotNull(result);
    assertThat(result, is(not(empty())));
  }

  @Test
  public void returnsEmptyListIfNoRechargePositionExists() {
    Point currentVehiclePoint = new Point("Current vehicle point");
    Vehicle vehicle = new Vehicle("Some vehicle")
        .withCurrentPosition(currentVehiclePoint.getReference());

    when(plantModelService.fetchObject(Point.class, currentVehiclePoint.getReference()))
        .thenReturn(currentVehiclePoint);

    rechargePosSupplier.initialize();

    List<Destination> result = rechargePosSupplier.findRechargeSequence(vehicle);
    assertNotNull(result);
    assertThat(result, is(empty()));
  }

  @Test
  public void returnsEmptyListIfAssignedRechargePositionDoesNotExist() {
    Point currentVehiclePoint = new Point("Current vehicle point");
    Vehicle vehicle = new Vehicle("Some vehicle")
        .withRechargeOperation("Do some recharging")
        .withCurrentPosition(currentVehiclePoint.getReference())
        .withProperty(Dispatcher.PROPKEY_ASSIGNED_RECHARGE_LOCATION, "someUnknownLocation");

    Point locationAccessPoint = new Point("Location access point")
        .withType(Point.Type.HALT_POSITION);

    LocationType rechargeLocType = new LocationType("Recharge location type")
        .withAllowedOperations(Arrays.asList("Recharge"));
    Location location = new Location("Recharge location", rechargeLocType.getReference());

    Location.Link link = new Location.Link(location.getReference(),
                                           locationAccessPoint.getReference());
    location = location.withAttachedLinks(new HashSet<>(Arrays.asList(link)));

    locationAccessPoint = locationAccessPoint.withAttachedLinks(new HashSet<>(Arrays.asList(link)));

    when(plantModelService.fetchObjects(Location.class))
        .thenReturn(Collections.singleton(location));
    when(plantModelService.fetchObject(LocationType.class, rechargeLocType.getReference()))
        .thenReturn(rechargeLocType);
    when(plantModelService.fetchObject(Point.class, currentVehiclePoint.getReference()))
        .thenReturn(currentVehiclePoint);
    when(plantModelService.fetchObject(Point.class, locationAccessPoint.getReference()))
        .thenReturn(locationAccessPoint);

    rechargePosSupplier.initialize();

    List<Destination> result = rechargePosSupplier.findRechargeSequence(vehicle);
    assertNotNull(result);
    assertThat(result, is(empty()));
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/model/StandardSystemModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.draw.DefaultDrawing;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.Figure;
import org.opentcs.data.model.ModelConstants;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.components.drawing.course.CoordinateBasedDrawingMethod;
import org.opentcs.guing.components.drawing.course.DrawingMethod;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import static org.opentcs.guing.model.ModelComponent.MISCELLANEOUS;
import static org.opentcs.guing.model.ModelComponent.NAME;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.OtherGraphicalElement;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.guing.util.ModelComponentFactory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Base implementation for a SystemModel.
 * Holds the vehicles and the layout of the model. The SystemModel has a map of base components
 * for each component type (e.g. points, locations, vehicles, ...).
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
class StandardSystemModel
    extends CompositeModelComponent
    implements SystemModel {

  /**
   * A Map that represents the main folder of the system model.
   * Maps a folder key to the main model component for that folder.
   */
  private final Map<FolderKey, ModelComponent> fMainFolders = new HashMap<>();
  /**
   * Maps a model component class to a main folder component.
   * Practically determines which folder a model component belongs to.
   */
  private final Map<Class<?>, ModelComponent> fParentFolders = new HashMap<>();
  /**
   * Maps model components to the corresponding figures.
   */
  private final Map<ModelComponent, Figure> figuresMap = new HashMap<>();
  /**
   * The drawing.
   */
  private final Drawing fDrawing = new DefaultDrawing();
  /**
   * The used drawing method.
   */
  private final DrawingMethod fDrawingMethod = new CoordinateBasedDrawingMethod();

  private final ModelComponentFactory modelComponentFactory;

  /**
   * Creates a new instance with a default drawing method.
   */
  @Inject
  public StandardSystemModel(ModelComponentFactory modelComponentFactory) {
    super("Model");
    this.modelComponentFactory = requireNonNull(modelComponentFactory, "modelComponentFactory");

    createMainFolders();
    setupParentFolders();
    createProperties();
  }

  @Override
  public KeyValueSetProperty getPropertyMiscellaneous() {
    return (KeyValueSetProperty) getProperty(MISCELLANEOUS);
  }

  @Override // SystemModel
  public void addMainFolder(FolderKey key, ModelComponent component) {
    fMainFolders.put(key, component);
  }

  @Override // SystemModel
  public ModelComponent getMainFolder(FolderKey key) {
    return fMainFolders.get(key);
  }

  @Override // SystemModel
  public ModelComponent getFolder(ModelComponent item) {
    if (item == null) {
      return null;
    }

    for (Class<?> c : fParentFolders.keySet()) {
      if (item.getClass() == c || c.isInstance(item)) {
        return fParentFolders.get(c);
      }
    }

    return null;
  }

  @Override // SystemModel
  public <T> List<T> getAll(FolderKey foldername, Class<T> classType) {
    List<T> items = new ArrayList<>();
    for (ModelComponent o : getMainFolder(foldername).getChildComponents()) {
      if (classType.isInstance(o)) {
        items.add(classType.cast(o));
      }
    }

    return items;
  }

  @Override
  public List<ModelComponent> getAll() {
    List<ModelComponent> items = new ArrayList<>();
    for (ModelComponent o : fMainFolders.values()) { //Iterate over folders
      if (o instanceof CompositeModelComponent) {
        items.addAll(getAll((CompositeModelComponent) o));
      }
      else {
        items.add(o);
      }
    }
    return items;
  }
  
  @Override
  public void onRestorationComplete(){
  }

  @Override
  public void registerFigure(ModelComponent component, Figure figure) {
    figuresMap.put(component, figure);
  }

  @Override
  public Figure getFigure(ModelComponent component) {
    return figuresMap.get(component);
  }

  @Override // SystemModel
  public Drawing getDrawing() {
    return fDrawing;
  }

  @Override // SystemModel
  public DrawingMethod getDrawingMethod() {
    return fDrawingMethod;
  }

  @Override
  public ModelComponent getModelComponent(String name) {
    for (ModelComponent folder : fMainFolders.values()) {
      ModelComponent component = getModelComponent(name, folder);
      if (component != null) {
        return component;
      }
    }

    return null;
  }

  @Override // SystemModel
  public List<VehicleModel> getVehicleModels() {
    return getAll(FolderKey.VEHICLES, VehicleModel.class);
  }

  @Override // SystemModel
  public VehicleModel getVehicleModel(String name) {
    for (VehicleModel vehicle : getVehicleModels()) {
      if (vehicle.getName().equals(name)) {
        return vehicle;
      }
    }

    return null;
  }

  @Override // SystemModel
  public LayoutModel getLayoutModel() {
    return (LayoutModel) getMainFolder(FolderKey.LAYOUT);
  }

  @Override // SystemModel
  public List<PointModel> getPointModels() {
    return getAll(FolderKey.POINTS, PointModel.class);
  }

  @Override // SystemModel
  public PointModel getPointModel(String name) {
    for (PointModel point : getPointModels()) {
      if (point.getName().equals(name)) {
        return point;
      }
    }

    return null;
  }

  @Override // SystemModel
  public List<LocationModel> getLocationModels() {
    return getAll(FolderKey.LOCATIONS, LocationModel.class);
  }

  @Override // SystemModel
  public List<LocationModel> getLocationModels(LocationTypeModel type) {
    List<LocationModel> items = new ArrayList<>();
    for (LocationModel location : getLocationModels()) {
      if (location.getLocationType() == type) {
        items.add(location);
      }
    }

    return items;
  }

  @Override // SystemModel
  public LocationModel getLocationModel(String name) {
    for (LocationModel location : getLocationModels()) {
      if (location.getName().equals(name)) {
        return location;
      }
    }

    return null;
  }

  @Override // SystemModel
  public List<PathModel> getPathModels() {
    return getAll(FolderKey.PATHS, PathModel.class);
  }

  @Override
  public PathModel getPathModel(String name) {
    for (PathModel path : getPathModels()) {
      if (path.getName().equals(name)) {
        return path;
      }
    }

    return null;
  }

  @Override // SystemModel
  public List<LinkModel> getLinkModels() {
    return getAll(FolderKey.LINKS, LinkModel.class);
  }

  @Override // SystemModel
  public List<LinkModel> getLinkModels(LocationTypeModel locationType) {
    List<LinkModel> items = new ArrayList<>();
    for (LinkModel ref : getLinkModels()) {
      if (ref.getLocation().getLocationType() == locationType) {
        items.add(ref);
      }
    }

    return items;
  }

  @Override // SystemModel
  public List<LocationTypeModel> getLocationTypeModels() {
    return getAll(FolderKey.LOCATION_TYPES, LocationTypeModel.class);
  }

  @Override // SystemModel
  public LocationTypeModel getLocationTypeModel(String name) {
    for (LocationTypeModel t : getLocationTypeModels()) {
      if (t.getName().equals(name)) {
        return t;
      }
    }

    return null;
  }

  @Override
  public BlockModel getBlockModel(String name) {
    for (BlockModel block : getBlockModels()) {
      if (block.getName().equals(name)) {
        return block;
      }
    }

    return null;
  }

  @Override // SystemModel
  public List<BlockModel> getBlockModels() {
    return getAll(FolderKey.BLOCKS, BlockModel.class);
  }

  @Override // SystemModel
  public List<OtherGraphicalElement> getOtherGraphicalElements() {
    return getAll(FolderKey.OTHER_GRAPHICAL_ELEMENTS, OtherGraphicalElement.class);
  }

  /**
   * Return all model components in a folder.
   *
   * @param folder The folder of which to get the components from.
   * @return A list of all model components in that folder.
   */
  private List<ModelComponent> getAll(CompositeModelComponent folder) {
    List<ModelComponent> result = new LinkedList<>();
    for (ModelComponent component : folder.getChildComponents()) {
      if (component instanceof CompositeModelComponent) {
        result.addAll(getAll((CompositeModelComponent) component));
      }
      else {
        result.add(component);
      }
    }
    return result;
  }

  private ModelComponent getModelComponent(String name, ModelComponent root) {
    if (root instanceof CompositeModelComponent) {
      for (ModelComponent subComponent : root.getChildComponents()) {
        ModelComponent result = getModelComponent(name, subComponent);
        if (result != null) {
          return result;
        }
      }
    }
    else if (Objects.equals(name, root.getName())) {
      return root;
    }
    return null;
  }

  /**
   * Creates the main folder in the system model.
   */
  private void createMainFolders() {
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverview.TREEVIEW_PATH);
    createMainFolder(this, FolderKey.VEHICLES,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_vehicles.name")));

    createMainFolder(this, FolderKey.LAYOUT, createDefaultLayoutModel());

    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.POINTS,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_points.name")));
    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.PATHS,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_paths.name")));
    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.LOCATIONS,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_locations.name")));
    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.LOCATION_TYPES,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_locationTypes.name")));
    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.LINKS,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_links.name")));
    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.BLOCKS,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_blocks.name")));
    createMainFolder(getMainFolder(FolderKey.LAYOUT), FolderKey.OTHER_GRAPHICAL_ELEMENTS,
                     new SimpleFolder(bundle.getString("standardSystemModel.folder_otherGraphicalElements.name")));
  }

  private LayoutModel createDefaultLayoutModel() {
    LayoutModel layoutModel = modelComponentFactory.createLayoutModel();
    layoutModel.setName(ModelConstants.DEFAULT_VISUAL_LAYOUT_NAME);
    LayerGroup defaultGroup = new LayerGroup(ModelConstants.DEFAULT_LAYER_GROUP_ID,
                                             ModelConstants.DEFAULT_LAYER_GROUP_NAME,
                                             true);
    layoutModel.getPropertyLayerGroups().getValue().put(defaultGroup.getId(), defaultGroup);
    Layer defaultLayer = new Layer(ModelConstants.DEFAULT_LAYER_ID,
                                   ModelConstants.DEFAULT_LAYER_ORDINAL,
                                   true,
                                   ModelConstants.DEFAULT_LAYER_NAME,
                                   ModelConstants.DEFAULT_LAYER_GROUP_ID);
    layoutModel.getPropertyLayerWrappers().getValue()
        .put(defaultLayer.getId(), new LayerWrapper(defaultLayer, defaultGroup));

    return layoutModel;
  }

  private void createProperties() {
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverview.TREEVIEW_PATH);

    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("standardSystemModel.property_name.description"));
    pName.setHelptext(bundle.getString("standardSystemModel.property_name.helptext"));
    setProperty(NAME, pName);

    KeyValueSetProperty pMiscellaneous = new KeyValueSetProperty(this);
    pMiscellaneous.setDescription("Miscellaneous properties");
    pMiscellaneous.setHelptext("Miscellaneous properties");
    setProperty(MISCELLANEOUS, pMiscellaneous);
  }

  /**
   * Creates a folder for the system model and the TreeView.
   */
  private void createMainFolder(ModelComponent parentFolder,
                                FolderKey key,
                                ModelComponent newFolder) {
    addMainFolder(key, newFolder);
    parentFolder.add(newFolder);
  }

  /**
   * Initialises the association between a main folder and a model component class.
   */
  private void setupParentFolders() {
    fParentFolders.put(VehicleModel.class, getMainFolder(FolderKey.VEHICLES));
    fParentFolders.put(LayoutModel.class, getMainFolder(FolderKey.LAYOUT));
    fParentFolders.put(PointModel.class, getMainFolder(FolderKey.POINTS));
    fParentFolders.put(PathModel.class, getMainFolder(FolderKey.PATHS));
    fParentFolders.put(LocationModel.class, getMainFolder(FolderKey.LOCATIONS));
    fParentFolders.put(LocationTypeModel.class, getMainFolder(FolderKey.LOCATION_TYPES));
    fParentFolders.put(LinkModel.class, getMainFolder(FolderKey.LINKS));
    fParentFolders.put(BlockModel.class, getMainFolder(FolderKey.BLOCKS));
    fParentFolders.put(OtherGraphicalElement.class, getMainFolder(FolderKey.OTHER_GRAPHICAL_ELEMENTS));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/AdapterCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import java.io.Serializable;

/**
 * A command a comm adapter may execute.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface AdapterCommand
    extends Serializable {

  /**
   * Executes the command.
   *
   * @param adapter The comm adapter to execute the command with.
   */
  void execute(VehicleCommAdapter adapter);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/PrioritizedReparkPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeReparkVehicleSelectionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Creates parking orders for idle vehicles already at a parking position to send them to higher
 * prioritized parking positions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PrioritizedReparkPhase
    extends AbstractParkingPhase {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PrioritizedReparkPhase.class);

  private final CompositeReparkVehicleSelectionFilter vehicleSelectionFilter;
  private final ParkingPositionPriorityComparator priorityComparator;

  @Inject
  public PrioritizedReparkPhase(
      InternalTransportOrderService orderService,
      PrioritizedParkingPositionSupplier parkingPosSupplier,
      Router router,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      TransportOrderUtil transportOrderUtil,
      DefaultDispatcherConfiguration configuration,
      CompositeReparkVehicleSelectionFilter vehicleSelectionFilter,
      ParkingPositionPriorityComparator priorityComparator) {
    super(orderService,
          parkingPosSupplier,
          router,
          assignmentCandidateSelectionFilter,
          transportOrderUtil,
          configuration);
    this.vehicleSelectionFilter = requireNonNull(vehicleSelectionFilter, "vehicleSelectionFilter");
    this.priorityComparator = requireNonNull(priorityComparator, "priorityComparator");
  }

  @Override
  public void run() {
    if (!getConfiguration().parkIdleVehicles()
        || !getConfiguration().considerParkingPositionPriorities()
        || !getConfiguration().reparkVehiclesToHigherPriorityPositions()) {
      return;
    }

    LOG.debug("Looking for parking vehicles to send to higher prioritized parking positions...");

    getOrderService().fetchObjects(Vehicle.class).stream()
        .filter(vehicle -> vehicleSelectionFilter.apply(vehicle).isEmpty())
        .sorted((vehicle1, vehicle2) -> {
          // Sort the vehicles based on the priority of the parking position they occupy
          Point point1 = getOrderService().fetchObject(Point.class, vehicle1.getCurrentPosition());
          Point point2 = getOrderService().fetchObject(Point.class, vehicle2.getCurrentPosition());
          return priorityComparator.compare(point1, point2);
        })
        .forEach(vehicle -> createParkingOrder(vehicle));
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/ProgressIndicator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

/**
 * Makes progress information available in some way.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ProgressIndicator {

  /**
   * Initializes the progress indicator, possibly resetting the percentage and
   * message.
   */
  void initialize();

  /**
   * Sets/publishes the current progress status.
   *
   * @param progressStatus The progress status.
   */
  void setProgress(ProgressStatus progressStatus);

  /**
   * Terminates the progress indicator, indicating that no further progress is
   * going to be published.
   * The progress indicator may be reused after a call to {@code initialize()}.
   */
  void terminate();
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v002/AllowedOperationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v002;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
public class AllowedOperationTO
    extends PlantModelElementTO {
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/DataObjectFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs;

import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;

/**
 * Creates model elements that can be used in tests.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DataObjectFactory {

  /**
   * Prefix to use for points.
   */
  private String pointNamePrefix = "MyPoint-";
  /**
   * Prefix to use for paths.
   */
  private String pathNamePrefix = "MyPath-";
  /**
   * Prefix to use for vehicles.
   */
  private String vehicleNamePrefix = "MyVehicle-";
  /**
   * Prefix to use for location types.
   */
  private String locTypeNamePrefix = "MyLocType-";
  /**
   * Prefix to use for locations.
   */
  private String locationNamePrefix = "MyLocation-";
  /**
   * counter to create unique names.
   */
  private int uniqueIdCounter;

  /**
   * Creates a new instance.
   */
  public DataObjectFactory() {
  }

  /**
   * Sets the suffix used for points.
   *
   * @param pointNamePrefix The suffix used for points.
   */
  public void setPointNamePrefix(String pointNamePrefix) {
    this.pointNamePrefix = pointNamePrefix;
  }

  /**
   * Sets the prefix used for paths.
   *
   * @param pathNamePrefix The prefix used for paths.
   */
  public void setPathNamePrefix(String pathNamePrefix) {
    this.pathNamePrefix = pathNamePrefix;
  }

  /**
   * Sets the prefix used for vehicles.
   *
   * @param vehicleNamePrefix The prefix used for vehicles.
   */
  public void setVehicleNamePrefix(String vehicleNamePrefix) {
    this.vehicleNamePrefix = vehicleNamePrefix;
  }

  /**
   * Sets the prefix used for location types.
   *
   * @param locTypeNamePrefix The prefix used for location types.
   */
  public void setLocTypeNamePrefix(String locTypeNamePrefix) {
    this.locTypeNamePrefix = locTypeNamePrefix;
  }

  /**
   * Sets the prefix used for locations.
   *
   * @param locationNamePrefix The prefix used for locations.
   */
  public void setLocationNamePrefix(String locationNamePrefix) {
    this.locationNamePrefix = locationNamePrefix;
  }

  /**
   * Creates a point.
   *
   * @return A new point.
   */
  public Point createPoint() {
    ++uniqueIdCounter;
    return new Point(pointNamePrefix + uniqueIdCounter);
  }

  /**
   * Creates a path from a start point to an end point.
   *
   * @param srcRef Reference to the start point.
   * @param dstRef Reference to the end point.
   * @return A new path from the start point to the end point.
   */
  public Path createPath(TCSObjectReference<Point> srcRef,
                         TCSObjectReference<Point> dstRef) {
    ++uniqueIdCounter;
    return new Path(pathNamePrefix + uniqueIdCounter, srcRef, dstRef);
  }

  /**
   * Creates a path leading to a destination point.
   * Creates an anonymous start point.
   *
   * @param dstRef Reference to the destination point.
   * @return A new path from an anonymous start point to the end point.
   */
  public Path createPath(TCSObjectReference<Point> dstRef) {
    Point srcPoint = createPoint();
    ++uniqueIdCounter;
    return createPath(srcPoint.getReference(), dstRef);
  }

  /**
   * Creates a path with anonymous start and destination points.
   *
   * @return A new path with anonymous start and end points.
   */
  public Path createPath() {
    Point dstPoint = createPoint();
    ++uniqueIdCounter;
    return createPath(dstPoint.getReference());
  }

  /**
   * Creates a vehicle.
   *
   * @return A new vehicle.
   */
  public Vehicle createVehicle() {
    ++uniqueIdCounter;
    return new Vehicle(vehicleNamePrefix + uniqueIdCounter);
  }

  /**
   * Creates a location type.
   *
   * @return A new location type.
   */
  public LocationType createLocationType() {
    ++uniqueIdCounter;
    return new LocationType(locTypeNamePrefix + uniqueIdCounter);
  }

  /**
   * Creates a location.
   *
   * @param locTypeRef Reference to the location type to use for the new location.
   * @return A new location with the location type.
   */
  public Location createLocation(TCSObjectReference<LocationType> locTypeRef) {
    ++uniqueIdCounter;
    return new Location(locationNamePrefix + uniqueIdCounter, locTypeRef);
  }

  /**
   * Creates a location with an anonymous location type.
   *
   * @return A new location with an anonymous location type.
   */
  public Location createLocation() {
    LocationType locType = createLocationType();
    ++uniqueIdCounter;
    return new Location(locationNamePrefix + uniqueIdCounter, locType.getReference());
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteQueryService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.Query;
import org.opentcs.components.kernel.services.QueryService;

/**
 * Declares the methods provided by the {@link QueryService} via RMI.
 *
 * <p>
 * The majority of the methods declared here have signatures analogous to their counterparts in
 * {@link QueryService}, with an additional {@link ClientID} parameter which serves the purpose
 * of identifying the calling client and determining its permissions.
 * </p>
 * <p>
 * To avoid redundancy, the semantics of methods that only pass through their arguments are not
 * explicitly documented here again. See the corresponding API documentation in
 * {@link QueryService} for these, instead.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RemoteQueryService
    extends Remote {

  // CHECKSTYLE:OFF
  <T> T query(ClientID clientId, Query<T> query)
      throws RemoteException;
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/MultipleDifferentValues.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.ResourceBundle;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class MultipleDifferentValues
    implements AcceptableInvalidValue {

  @Override
  public String getDescription() {
    return ResourceBundle.getBundle(BUNDLE_PATH)
        .getString("multipleDifferentValues.description");
  }

  @Override
  public String getHelptext() {
    return ResourceBundle.getBundle(BUNDLE_PATH)
        .getString("multipleDifferentValues.helptext");
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/menus/menubar/ViewPluginPanelsMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.inject.Inject;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.opentcs.access.Kernel;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.application.PluginPanelManager;
import org.opentcs.guing.application.action.view.AddPluginPanelAction;
import org.opentcs.guing.components.dockable.DockingManager;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.guing.util.PanelRegistry;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewPluginPanelsMenu
    extends JMenu {

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(I18nPlantOverview.MENU_PATH);

  /**
   * The plugin panel manager.
   */
  private final PluginPanelManager pluginPanelManager;
  /**
   * Provides the registered plugin panel factories.
   */
  private final PanelRegistry panelRegistry;
  /**
   * Manages docking frames.
   */
  private final DockingManager dockingManager;

  @Inject
  public ViewPluginPanelsMenu(PluginPanelManager pluginPanelManager,
                              PanelRegistry panelRegistry,
                              DockingManager dockingManager) {
    super(BUNDLE.getString("viewPluginPanelsMenu.text"));

    this.pluginPanelManager = requireNonNull(pluginPanelManager, "pluginPanelManager");
    this.panelRegistry = requireNonNull(panelRegistry, "panelRegistry");
    this.dockingManager = requireNonNull(dockingManager, "dockingManager");
  }

  public void setOperationMode(OperationMode mode) {
    requireNonNull(mode, "mode");

    evaluatePluginPanels(mode);
  }

  /**
   * Removes/adds plugin panels depending on the <code>OperationMode</code>.
   *
   * @param operationMode The operation mode.
   */
  private void evaluatePluginPanels(OperationMode operationMode) {
    Kernel.State kernelState = OperationMode.equivalent(operationMode);
    if (kernelState == null) {
      return;
    }

    removeAll();

    SortedSet<PluggablePanelFactory> factories = new TreeSet<>((factory1, factory2) -> {
      return factory1.getPanelDescription().compareTo(factory2.getPanelDescription());
    });
    factories.addAll(panelRegistry.getFactories());

    for (final PluggablePanelFactory factory : factories) {
      if (factory.providesPanel(kernelState)) {
        String title = factory.getPanelDescription();
        final JCheckBoxMenuItem utilMenuItem = new JCheckBoxMenuItem();
        utilMenuItem.setAction(new AddPluginPanelAction(pluginPanelManager, factory));
        utilMenuItem.setText(title);
        dockingManager.addPropertyChangeListener(new PluginPanelPropertyHandler(utilMenuItem));
        add(utilMenuItem);
      }
    }
    // If the menu is empty, add a single disabled menu item to it that explains
    // to the user that no plugin panels are available.
    if (getMenuComponentCount() == 0) {
      JMenuItem dummyItem = new JMenuItem(BUNDLE.getString("viewPluginPanelsMenu.menuItem_none.text"));
      dummyItem.setEnabled(false);
      add(dummyItem);
    }
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/VelocityListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle;

/**
 * Declares the method that is called to notify a listener about a new velocity
 * value.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VelocityListener {

  /**
   * Called when a new velocity value (in mm/s) has been computed.
   *
   * @param velocityValue The new velocity value that has been computed.
   */
  void addVelocityValue(int velocityValue);
}


<|start_filename|>openTCS-Kernel/src/dist/generateKeystores.bat<|end_filename|>
@echo off
rem
rem Start SSL keystore and truststore generation.
rem

rem Don't export variables to the parent shell.
setlocal

rem Set the path to where keytool is located. Keytool comes with the Java JRE.
set KEYTOOL_PATH="keytool"

rem Try to execute keytool
%KEYTOOL_PATH% 2>nul
if %ERRORLEVEL% neq 0 (
	if %KEYTOOL_PATH% equ "keytool" (
		echo Error: Could not find keytool in PATH.
	) else (
		echo Error: Could not find keytool in %KEYTOOL_PATH%.
	)
	exit /B %ERRORLEVEL%
)

rem Set base directory names.
set OPENTCS_HOME=.
set OPENTCS_CONFIGDIR=%OPENTCS_HOME%\config
set OUTPUTDIR=%OPENTCS_CONFIGDIR%

rem Set paths to generate files at.
set KEYSTORE_FILEPATH=%OUTPUTDIR%\keystore.p12
set TRUSTSTORE_FILEPATH=%OUTPUTDIR%\truststore.p12
set CERTIFICATE_FILEPATH=%OUTPUTDIR%\certificate.cer

rem Set the password used for generating the stores.
set PASSWORD=password

echo Deleting previously generated keystore and truststore...
del %KEYSTORE_FILEPATH% 2>nul
del %TRUSTSTORE_FILEPATH% 2>nul
del %CERTIFICATE_FILEPATH% 2>nul

rem Generates a keypair wrapped in a self-signed (X.509) certificate.
rem Some defaults of the -genkeypair command: -alias "mykey" -keyalg "DSA" -keysize 1024 -validity 90
echo Generating a new keystore in %KEYSTORE_FILEPATH%...
%KEYTOOL_PATH% -genkeypair -alias openTCS -keyalg RSA -dname "c=DE" -storepass %PASSWORD% -keypass %PASSWORD% -validity 365 -storetype PKCS12 -keystore %KEYSTORE_FILEPATH%

rem Exports the (wrapping) self-signed certificate from the generated keypair.
rem '-rfc' - Output the certificate in a printable encoding format (by default the -export command outputs a certificate in binary encoding)
rem '2>nul' - Suppress output of this command
%KEYTOOL_PATH% -exportcert -alias openTCS -file %CERTIFICATE_FILEPATH% -keystore %KEYSTORE_FILEPATH% -storepass %PASSWORD% -rfc 2>nul

rem Adds the exported certificate to a new keystore and its trusted certificates.
echo Generating a new truststore in %TRUSTSTORE_FILEPATH%...
%KEYTOOL_PATH% -importcert -alias openTCS -file %CERTIFICATE_FILEPATH% -storepass %PASSWORD% -storetype PKCS12 -keystore %TRUSTSTORE_FILEPATH% -noprompt 2>nul

rem Delete the exported certificate since it's not really needed.
del %CERTIFICATE_FILEPATH%

echo Copy the generated truststore to the openTCS PlantOverview's \config folder or a corresponding location of your application.

pause


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/edgeevaluator/EdgeEvaluatorExplicitProperties.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.edgeevaluator;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import static org.opentcs.components.kernel.Router.PROPKEY_ROUTING_COST_FORWARD;
import static org.opentcs.components.kernel.Router.PROPKEY_ROUTING_COST_REVERSE;
import static org.opentcs.components.kernel.Router.PROPKEY_ROUTING_GROUP;
import org.opentcs.components.kernel.routing.Edge;
import org.opentcs.components.kernel.routing.EdgeEvaluator;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Uses an edge's explicit routing cost (given as a property value) as its weight.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EdgeEvaluatorExplicitProperties
    implements EdgeEvaluator {

  /**
   * A key used for selecting this evaluator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "EXPLICIT_PROPERTIES";
  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(EdgeEvaluatorExplicitProperties.class);
  /**
   * This class's configuration.
   */
  private final ExplicitPropertiesConfiguration configuration;

  @Inject
  public EdgeEvaluatorExplicitProperties(ExplicitPropertiesConfiguration configuration) {
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public double computeWeight(Edge edge, Vehicle vehicle) {
    requireNonNull(edge, "edge");
    requireNonNull(vehicle, "vehicle");

    String group = extractVehicleGroup(vehicle);

    if (edge.isTravellingReverse()) {
      return parseCosts(extractRoutingCostString(edge.getPath(),
                                                 PROPKEY_ROUTING_COST_REVERSE + group));
    }
    else {
      return parseCosts(extractRoutingCostString(edge.getPath(),
                                                 PROPKEY_ROUTING_COST_FORWARD + group));
    }
  }

  private String extractVehicleGroup(Vehicle vehicle) {
    String group = vehicle.getProperty(PROPKEY_ROUTING_GROUP);

    return group == null ? "" : group;
  }

  private String extractRoutingCostString(Path path, String propertyKey) {
    String propVal = path.getProperty(propertyKey);

    if (propVal == null) {
      LOG.warn(
          "No routing cost property value for key '{}' in path '{}'. Using configured default: {}",
          propertyKey,
          path,
          configuration.defaultValue()
      );
      return configuration.defaultValue();
    }
    return propVal;
  }

  private double parseCosts(String costs) {
    try {
      return Double.parseDouble(costs);
    }
    catch (NumberFormatException exc) {
      LOG.warn("Exception parsing routing cost value '{}'.", costs, exc);
      return Double.POSITIVE_INFINITY;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/SelectionProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property whose value is one out of a list of possible values.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @param <E> The type of the enum.
 */
public class SelectionProperty<E extends Enum<E>>
    extends AbstractProperty
    implements Selectable<E> {

  /**
   * The possible values.
   */
  private List<E> fPossibleValues;

  /**
   * Creates a new instance.
   *
   * @param model The model component.
   */
  public SelectionProperty(ModelComponent model) {
    this(model, new ArrayList<>(), "");
  }

  /**
   * Creates a new instance.
   *
   * @param model The model Component.
   * @param possibleValues The possible values.
   * @param value The value.
   */
  public SelectionProperty(ModelComponent model, List<E> possibleValues,
                           Object value) {
    super(model);
    setPossibleValues(possibleValues);
    fValue = value;
  }

  @Override
  public Object getComparableValue() {
    return fValue;
  }

  /**
   * Sets the possible values for this property.
   *
   * @param possibleValues A list of possible values.
   */
  @Override
  public void setPossibleValues(List<E> possibleValues) {
    fPossibleValues = Objects.requireNonNull(possibleValues, "possibleValues is null");
  }

  @Override
  public void setValue(Object value) {
    if (fPossibleValues.contains(value)
        || value instanceof AcceptableInvalidValue) {
      fValue = value;
    }
  }

  @Override
  public String toString() {
    return getValue().toString();
  }

  @Override
  public List<E> getPossibleValues() {
    return fPossibleValues;
  }

  @Override
  public void copyFrom(Property property) {
    AbstractProperty selectionProperty = (AbstractProperty) property;
    setValue(selectionProperty.getValue());
  }
}


<|start_filename|>openTCS-API-Injection/src/main/java/org/opentcs/customizations/plantoverview/package-info.java<|end_filename|>
/**
 * Components supporting extension and customization of the openTCS plant overview application.
 */
package org.opentcs.customizations.plantoverview;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/OrderReservationPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;

/**
 * Stores reservations of orders for vehicles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderReservationPool {

  /**
   * Reservations of orders for vehicles.
   */
  private final Map<TCSObjectReference<TransportOrder>, TCSObjectReference<Vehicle>> orderReservations
      = Collections.synchronizedMap(new HashMap<TCSObjectReference<TransportOrder>, TCSObjectReference<Vehicle>>());

  /**
   * Creates a new instance.
   */
  @Inject
  public OrderReservationPool() {
  }

  /**
   * Clears all reservations.
   */
  public void clear() {
    orderReservations.clear();
  }

  /**
   * Checks whether there is a reservation of the given transport order for any vehicle.
   *
   * @param orderRef A reference to the transport order.
   * @return <code>true</code> if, and only if, there is a reservation.
   */
  public boolean isReserved(@Nonnull TCSObjectReference<TransportOrder> orderRef) {
    return orderReservations.containsKey(orderRef);
  }

  public void addReservation(@Nonnull TCSObjectReference<TransportOrder> orderRef,
                             @Nonnull TCSObjectReference<Vehicle> vehicleRef) {
    orderReservations.put(orderRef, vehicleRef);
  }

  public void removeReservation(@Nonnull TCSObjectReference<TransportOrder> orderRef) {
    orderReservations.remove(orderRef);
  }

  public void removeReservations(@Nonnull TCSObjectReference<Vehicle> vehicleRef) {
    orderReservations.values().removeIf(value -> vehicleRef.equals(value));
  }

  public List<TCSObjectReference<TransportOrder>> findReservations(
      @Nonnull TCSObjectReference<Vehicle> vehicleRef) {
    return orderReservations.entrySet().stream()
        .filter(entry -> vehicleRef.equals(entry.getValue()))
        .map(entry -> entry.getKey())
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/CompositeObjectHistoryEntryFormatter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.components.plantoverview.ObjectHistoryEntryFormatter;
import org.opentcs.data.ObjectHistory;

/**
 * A composite formatter for history entries that first tries to apply all registered formatters,
 * then {@link StandardObjectHistoryEntryFormatter}, then a fallback function to ensure that the
 * returned value is <em>never empty</em>.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeObjectHistoryEntryFormatter
    implements ObjectHistoryEntryFormatter {

  /**
   * The actual formatters.
   */
  private final List<ObjectHistoryEntryFormatter> formatters = new ArrayList<>();

  /**
   * Creates a new instance.
   *
   * @param customFormatters The set of custom formatters.
   */
  @Inject
  public CompositeObjectHistoryEntryFormatter(Set<ObjectHistoryEntryFormatter> customFormatters) {
    for (ObjectHistoryEntryFormatter formatter : customFormatters) {
      formatters.add(formatter);
    }

    formatters.add(new StandardObjectHistoryEntryFormatter());
    formatters.add(this::fallbackFormat);
  }

  @Override
  public Optional<String> apply(ObjectHistory.Entry entry) {
    return formatters.stream()
        .map(formatter -> formatter.apply(entry))
        .filter(result -> result.isPresent())
        .map(result -> result.get())
        .findFirst();
  }

  private Optional<String> fallbackFormat(ObjectHistory.Entry entry) {
    return Optional.of(
        "eventCode: '" + entry.getEventCode()
        + "', supplement: '" + entry.getSupplement().toString() + '\''
    );
  }

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardVehicleService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.InternalVehicleService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.components.kernel.services.VehicleService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
import org.opentcs.drivers.vehicle.management.AttachmentInformation;
import org.opentcs.drivers.vehicle.management.VehicleProcessModelTO;
import org.opentcs.kernel.extensions.controlcenter.vehicles.AttachmentManager;
import org.opentcs.kernel.extensions.controlcenter.vehicles.VehicleEntry;
import org.opentcs.kernel.extensions.controlcenter.vehicles.VehicleEntryPool;
import org.opentcs.kernel.vehicles.LocalVehicleControllerPool;
import org.opentcs.kernel.vehicles.VehicleCommAdapterRegistry;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.TCSObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is the standard implementation of the {@link VehicleService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardVehicleService
    extends AbstractTCSObjectService
    implements InternalVehicleService {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StandardVehicleService.class);
  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The container of all course model and transport order objects.
   */
  private final TCSObjectPool globalObjectPool;
  /**
   * A pool of vehicle controllers.
   */
  private final LocalVehicleControllerPool vehicleControllerPool;
  /**
   * A pool of vehicle entries.
   */
  private final VehicleEntryPool vehicleEntryPool;
  /**
   * The attachment manager.
   */
  private final AttachmentManager attachmentManager;
  /**
   * The registry for all communication adapters.
   */
  private final VehicleCommAdapterRegistry commAdapterRegistry;
  /**
   * The model facade to the object pool.
   */
  private final Model model;

  /**
   * Creates a new instance.
   *
   * @param objectService The tcs object service.
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param globalObjectPool The object pool to be used.
   * @param vehicleControllerPool The controller pool to be used.
   * @param vehicleEntryPool The pool of vehicle entries to be used.
   * @param attachmentManager The attachment manager.
   * @param commAdapterRegistry The registry for all communication adapters.
   * @param model The model to be used.
   */
  @Inject
  public StandardVehicleService(TCSObjectService objectService,
                                @GlobalSyncObject Object globalSyncObject,
                                TCSObjectPool globalObjectPool,
                                LocalVehicleControllerPool vehicleControllerPool,
                                VehicleEntryPool vehicleEntryPool,
                                AttachmentManager attachmentManager,
                                VehicleCommAdapterRegistry commAdapterRegistry,
                                Model model) {
    super(objectService);
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.globalObjectPool = requireNonNull(globalObjectPool, "globalObjectPool");
    this.vehicleControllerPool = requireNonNull(vehicleControllerPool, "vehicleControllerPool");
    this.vehicleEntryPool = requireNonNull(vehicleEntryPool, "vehicleEntryPool");
    this.attachmentManager = requireNonNull(attachmentManager, "attachmentManager");
    this.commAdapterRegistry = requireNonNull(commAdapterRegistry, "commAdapterRegistry");
    this.model = requireNonNull(model, "model");
  }

  @Override
  public void updateVehicleEnergyLevel(TCSObjectReference<Vehicle> ref, int energyLevel)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleEnergyLevel(ref, energyLevel);
    }
  }

  @Override
  public void updateVehicleLoadHandlingDevices(TCSObjectReference<Vehicle> ref,
                                               List<LoadHandlingDevice> devices)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleLoadHandlingDevices(ref, devices);
    }
  }

  @Override
  public void updateVehicleNextPosition(TCSObjectReference<Vehicle> vehicleRef,
                                        TCSObjectReference<Point> pointRef)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleNextPosition(vehicleRef, pointRef);
    }
  }

  @Override
  public void updateVehicleOrderSequence(TCSObjectReference<Vehicle> vehicleRef,
                                         TCSObjectReference<OrderSequence> sequenceRef)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleOrderSequence(vehicleRef, sequenceRef);
    }
  }

  @Override
  public void updateVehicleOrientationAngle(TCSObjectReference<Vehicle> ref, double angle)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleOrientationAngle(ref, angle);
    }
  }

  @Override
  public void updateVehiclePosition(TCSObjectReference<Vehicle> vehicleRef,
                                    TCSObjectReference<Point> pointRef)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      LOG.debug("Vehicle {} has reached point {}.", vehicleRef, pointRef);
      model.setVehiclePosition(vehicleRef, pointRef);
    }
  }

  @Override
  public void updateVehiclePrecisePosition(TCSObjectReference<Vehicle> ref, Triple position)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehiclePrecisePosition(ref, position);
    }
  }

  @Override
  public void updateVehicleProcState(TCSObjectReference<Vehicle> ref, Vehicle.ProcState state)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      LOG.debug("Updating procState of vehicle {} to {}...", ref.getName(), state);
      model.setVehicleProcState(ref, state);
    }
  }

  @Override
  public void updateVehicleRechargeOperation(TCSObjectReference<Vehicle> ref,
                                             String rechargeOperation)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleRechargeOperation(ref, rechargeOperation);
    }
  }

  @Override
  public void updateVehicleRouteProgressIndex(TCSObjectReference<Vehicle> ref, int index)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleRouteProgressIndex(ref, index);
    }
  }

  @Override
  public void updateVehicleClaimedResources(TCSObjectReference<Vehicle> ref,
                                            List<Set<TCSResourceReference<?>>> resources)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleClaimedResources(ref, resources);
    }
  }

  @Override
  public void updateVehicleAllocatedResources(TCSObjectReference<Vehicle> ref,
                                              List<Set<TCSResourceReference<?>>> resources)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleAllocatedResources(ref, resources);
    }
  }

  @Override
  public void updateVehicleState(TCSObjectReference<Vehicle> ref, Vehicle.State state)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleState(ref, state);
    }
  }

  @Override
  public void updateVehicleTransportOrder(TCSObjectReference<Vehicle> vehicleRef,
                                          TCSObjectReference<TransportOrder> orderRef)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleTransportOrder(vehicleRef, orderRef);
    }
  }

  @Override
  public void attachCommAdapter(TCSObjectReference<Vehicle> ref,
                                VehicleCommAdapterDescription description)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      attachmentManager.attachAdapterToVehicle(ref.getName(),
                                               commAdapterRegistry.findFactoryFor(description));
    }
  }

  @Override
  public void disableCommAdapter(TCSObjectReference<Vehicle> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      VehicleEntry entry = vehicleEntryPool.getEntryFor(ref.getName());
      if (entry == null) {
        throw new IllegalArgumentException("No vehicle entry found for" + ref.getName());
      }

      entry.getCommAdapter().disable();
    }
  }

  @Override
  public void enableCommAdapter(TCSObjectReference<Vehicle> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      VehicleEntry entry = vehicleEntryPool.getEntryFor(ref.getName());
      if (entry == null) {
        throw new IllegalArgumentException("No vehicle entry found for " + ref.getName());
      }

      entry.getCommAdapter().enable();
    }
  }

  @Override
  public AttachmentInformation fetchAttachmentInformation(TCSObjectReference<Vehicle> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      return attachmentManager.getAttachmentInformation(ref.getName());
    }
  }

  @Override
  public VehicleProcessModelTO fetchProcessModel(TCSObjectReference<Vehicle> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      VehicleEntry entry = vehicleEntryPool.getEntryFor(ref.getName());
      if (entry == null) {
        throw new IllegalArgumentException("No vehicle entry found for " + ref.getName());
      }

      return entry.getCommAdapter().createTransferableProcessModel();
    }
  }

  @Override
  public void sendCommAdapterCommand(TCSObjectReference<Vehicle> ref, AdapterCommand command)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      vehicleControllerPool
          .getVehicleController(ref.getName())
          .sendCommAdapterCommand(command);
    }
  }

  @Override
  public void sendCommAdapterMessage(TCSObjectReference<Vehicle> ref, Object message)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      vehicleControllerPool
          .getVehicleController(ref.getName())
          .sendCommAdapterMessage(message);
    }
  }

  @Override
  public void updateVehicleIntegrationLevel(TCSObjectReference<Vehicle> ref,
                                            Vehicle.IntegrationLevel integrationLevel)
      throws ObjectUnknownException, KernelRuntimeException {
    synchronized (globalSyncObject) {
      Vehicle vehicle = fetchObject(Vehicle.class, ref);

      if (vehicle.isProcessingOrder()
          && (integrationLevel == Vehicle.IntegrationLevel.TO_BE_IGNORED
              || integrationLevel == Vehicle.IntegrationLevel.TO_BE_NOTICED)) {
        throw new IllegalArgumentException(
            String.format("%s: Cannot change integration level to %s while processing orders.",
                          vehicle.getName(),
                          integrationLevel.name())
        );
      }

      model.setVehicleIntegrationLevel(ref, integrationLevel);
    }
  }

  @Override
  public void updateVehicleAllowedOrderTypes(TCSObjectReference<Vehicle> ref,
                                             Set<String> allowedOrderTypes)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setVehicleAllowedOrderTypes(ref, allowedOrderTypes);
    }
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/GuestUserCredentials.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

/**
 * Defines the credentials for a guest user account.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface GuestUserCredentials {

  /**
   * The default/guest user name.
   */
  String USER = "Alice";
  /**
   * The default/guest password.
   */
  String PASSWORD = "<PASSWORD>";
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/xmlbinding/TransportOrderEntry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.xmlbinding;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import org.opentcs.guing.plugins.panels.loadgenerator.DriveOrderStructure;
import org.opentcs.guing.plugins.panels.loadgenerator.TransportOrderData;

/**
 * Stores a transport order definition for XML marshalling/unmarshalling.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
@XmlType(propOrder = {"properties", "driveOrders", "deadline", "intendedVehicle"})
public class TransportOrderEntry {

  /**
   * The transport order's deadline.
   */
  private Deadline deadline = Deadline.PLUS_TWO_HOURS;
  /**
   * The drive orders the transport order consists of.
   */
  private final List<DriveOrderEntry> driveOrders = new ArrayList<>();
  /**
   * The name of the vehicle intended to process the transport order.
   */
  private String intendedVehicle;
  /**
   * Properties of the transport order data.
   */
  private List<XMLMapEntry> properties = new LinkedList<>();

  /**
   * Creates a new instance.
   *
   * @param deadline The deadline of this transport order
   * @param driveOrders A list containing the drive orders
   * @param intendedVehicle The intended vehicle for this transport order
   * @param properties A map containing the properties of this transport order
   */
  public TransportOrderEntry(TransportOrderData.Deadline deadline,
                                    List<DriveOrderStructure> driveOrders,
                                    String intendedVehicle,
                                    Map<String, String> properties) {
    switch (deadline) {
      case MINUS_FIVE_MINUTES:
        this.deadline = Deadline.MINUS_FIVE_MINUTES;
        break;
      case PLUS_FIVE_MINUTES:
        this.deadline = Deadline.PLUS_FIVE_MINUTES;
        break;
      case MINUS_HALF_HOUR:
        this.deadline = Deadline.MINUS_HALF_HOUR;
        break;
      case PLUS_HALF_HOUR:
        this.deadline = Deadline.PLUS_HALF_HOUR;
        break;
      case PLUS_ONE_HOUR:
        this.deadline = Deadline.PLUS_ONE_HOUR;
        break;
      case PLUS_TWO_HOURS:
      default:
        this.deadline = Deadline.PLUS_TWO_HOURS;
        break;
    }
    this.intendedVehicle = intendedVehicle;
    for (Map.Entry<String, String> curEntry : properties.entrySet()) {
      this.properties.add(
          new XMLMapEntry(curEntry.getKey(), curEntry.getValue()));
    }
    for (DriveOrderStructure curDOS : driveOrders) {
      this.driveOrders.add(
          new DriveOrderEntry(curDOS.getDriveOrderLocation().getName(),
                                     curDOS.getDriveOrderVehicleOperation()));
    }
  }

  /**
   * Creates a new instance.
   */
  public TransportOrderEntry() {
  }

  /**
   * Returns the properties of this transport order.
   *
   * @return The properties
   */
  @XmlElement(name = "property", required = true)
  //@XmlJavaTypeAdapter(MapAdapter.class)
  public List<XMLMapEntry> getProperties() {
    return properties;
  }

  /**
   * Returns the list of drive orders.
   *
   * @return The list of drive orders.
   */
  @XmlElement(name = "driveOrder", required = true)
  public List<DriveOrderEntry> getDriveOrders() {
    return driveOrders;
  }

  /**
   * Returns a deadline.
   *
   * @return The deadline.
   */
  @XmlAttribute(name = "deadline", required = true)
  public Deadline getDeadline() {
    return this.deadline;
  }

  /**
   * Sets the transport order's deadline.
   *
   * @param deadline The new deadline.
   */
  public void setDeadline(Deadline deadline) {
    this.deadline = requireNonNull(deadline, "deadline");
  }

  /**
   * Returns a reference to the vehicle intended to process the order.
   *
   * @return A reference to the vehicle intended to process the order.
   */
  @XmlAttribute(name = "intendedVehicle", required = true)
  public String getIntendedVehicle() {
    return intendedVehicle;
  }

  /**
   * Sets a reference to the vehicle intended to process the order.
   *
   * @param vehicle A reference to the vehicle intended to process the order.
   */
  public void setIntendedVehicle(String vehicle) {
    intendedVehicle = vehicle;
  }

  /**
   * The enumeration of possible default deadline values.
   */
  public static enum Deadline {

    /**
     * The deadline value is five minutes in the past.
     */
    MINUS_FIVE_MINUTES,
    /**
     * The deadline value is five minutes in the future.
     */
    PLUS_FIVE_MINUTES,
    /**
     * The deadline value is a half hour in the past.
     */
    MINUS_HALF_HOUR,
    /**
     * The deadline value is a half hour in the future.
     */
    PLUS_HALF_HOUR,
    /**
     * The deadline value is a one hour in the future.
     */
    PLUS_ONE_HOUR,
    /**
     * The deadline value is two hours in the future.
     */
    PLUS_TWO_HOURS;
  }

  /**
   * A class to marshal the map of properties.
   */
  @XmlType
  public static class XMLMapEntry {

    /**
     * The key.
     */
    private String key;
    /**
     * The value.
     */
    private String value;

    /**
     * Creates an empty XMLMalEntry.
     */
    public XMLMapEntry() {
    }

    /**
     * Creates a new XMLMapEntry.
     *
     * @param key The key
     * @param value The value
     */
    public XMLMapEntry(String key, String value) {
      this.key = key;
      this.value = value;
    }

    @XmlAttribute
    public String getKey() {
      return key;
    }

    public void setKey(String key) {
      this.key = key;
    }

    @XmlAttribute
    public String getValue() {
      return value;
    }

    public void setValue(String value) {
      this.value = value;
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/Vehicle.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.awt.Color;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.order.OrderConstants;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;
import static org.opentcs.util.Assertions.checkArgument;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * Describes a vehicle's current state.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Vehicle
    extends TCSObject<Vehicle>
    implements Serializable {

  /**
   * A value indicating that no route steps have been travelled for the current drive order, yet.
   */
  public static final int ROUTE_INDEX_DEFAULT = -1;
  /**
   * The key for a property to store the class name of the preferred communication adapter (factory)
   * for this vehicle.
   */
  public static final String PREFERRED_ADAPTER = "tcs:preferredAdapterClass";
  /**
   * This vehicle's length (in mm).
   */
  private final int length;
  /**
   * The value at/above which the vehicle's energy level is considered "good".
   */
  private final int energyLevelGood;
  /**
   * The value at/below which the vehicle's energy level is considered "critical".
   */
  private final int energyLevelCritical;
  /**
   * The value at/above which the vehicle's energy level is considered fully recharged.
   */
  private final int energyLevelFullyRecharged;
  /**
   * The value at/above which the vehicle's energy level is considered sufficiently recharged.
   */
  private final int energyLevelSufficientlyRecharged;
  /**
   * This vehicle's remaining energy (in percent of the maximum).
   */
  private final int energyLevel;
  /**
   * This vehicle's maximum velocity (in mm/s).
   */
  private final int maxVelocity;
  /**
   * This vehicle's maximum reverse velocity (in mm/s).
   */
  private final int maxReverseVelocity;
  /**
   * The operation the vehicle's current communication adapter accepts as a command to recharge the
   * vehicle.
   */
  private final String rechargeOperation;
  /**
   * The current (state of the) load handling devices of this vehicle.
   */
  private final List<LoadHandlingDevice> loadHandlingDevices;
  /**
   * This vehicle's current state.
   */
  private final State state;
  /**
   * This vehicle's current processing state.
   */
  private final ProcState procState;
  /**
   * This vehicle's integration level.
   */
  private final IntegrationLevel integrationLevel;
  /**
   * A reference to the transport order this vehicle is currently processing.
   */
  private final TCSObjectReference<TransportOrder> transportOrder;
  /**
   * A reference to the order sequence this vehicle is currently processing.
   */
  private final TCSObjectReference<OrderSequence> orderSequence;
  /**
   * The set of transport order types this vehicle is allowed to process.
   */
  private final Set<String> allowedOrderTypes;
  /**
   * The index of the last route step travelled for the current drive order of the current transport
   * order.
   */
  private final int routeProgressIndex;
  /**
   * The resources this vehicle has claimed for future allocation.
   */
  private final List<Set<TCSResourceReference<?>>> claimedResources;
  /**
   * The resources this vehicle has allocated.
   */
  private final List<Set<TCSResourceReference<?>>> allocatedResources;
  /**
   * A reference to the point which this vehicle currently occupies.
   */
  private final TCSObjectReference<Point> currentPosition;
  /**
   * A reference to the point which this vehicle is expected to be seen at next.
   */
  private final TCSObjectReference<Point> nextPosition;
  /**
   * The vehicle's precise position in world coordinates [mm], independent from logical
   * positions/point names.
   * Set to <code>null</code> if the vehicle hasn't provided a precise position.
   */
  private final Triple precisePosition;
  /**
   * The vehicle's current orientation angle (-360..360).
   * Set to <code>Double.NaN</code> if the vehicle hasn't provided an orientation angle.
   */
  private final double orientationAngle;
  /**
   * The information regarding the grahical representation of this vehicle.
   */
  private final Layout layout;

  /**
   * Creates a new vehicle.
   *
   * @param name The new vehicle's name.
   */
  public Vehicle(String name) {
    super(name);
    this.length = 1000;
    this.energyLevelGood = 90;
    this.energyLevelCritical = 30;
    this.energyLevelFullyRecharged = 90;
    this.energyLevelSufficientlyRecharged = 30;
    this.maxVelocity = 1000;
    this.maxReverseVelocity = 1000;
    this.rechargeOperation = "CHARGE";
    this.procState = ProcState.IDLE;
    this.transportOrder = null;
    this.orderSequence = null;
    this.allowedOrderTypes = new HashSet<>(Arrays.asList(OrderConstants.TYPE_ANY));
    this.routeProgressIndex = ROUTE_INDEX_DEFAULT;
    this.claimedResources = List.of();
    this.allocatedResources = List.of();
    this.state = State.UNKNOWN;
    this.integrationLevel = IntegrationLevel.TO_BE_RESPECTED;
    this.currentPosition = null;
    this.nextPosition = null;
    this.precisePosition = null;
    this.orientationAngle = Double.NaN;
    this.energyLevel = 100;
    this.loadHandlingDevices = new ArrayList<>();
    this.layout = new Layout();
  }

  private Vehicle(String name,
                  Map<String, String> properties,
                  ObjectHistory history,
                  int length,
                  int energyLevelGood,
                  int energyLevelCritical,
                  int energyLevelFullyRecharged,
                  int energyLevelSufficientlyRecharged,
                  int maxVelocity,
                  int maxReverseVelocity,
                  String rechargeOperation,
                  ProcState procState,
                  TCSObjectReference<TransportOrder> transportOrder,
                  TCSObjectReference<OrderSequence> orderSequence,
                  Set<String> allowedOrderTypes,
                  int routeProgressIndex,
                  List<Set<TCSResourceReference<?>>> claimedResources,
                  List<Set<TCSResourceReference<?>>> allocatedResources,
                  State state,
                  IntegrationLevel integrationLevel,
                  TCSObjectReference<Point> currentPosition,
                  TCSObjectReference<Point> nextPosition,
                  Triple precisePosition,
                  double orientationAngle,
                  int energyLevel,
                  List<LoadHandlingDevice> loadHandlingDevices,
                  Layout layout) {
    super(name, properties, history);
    this.length = checkInRange(length, 1, Integer.MAX_VALUE, "length");
    this.energyLevelGood = checkInRange(energyLevelGood, 0, 100, "energyLevelGood");
    this.energyLevelCritical = checkInRange(energyLevelCritical, 0, 100, "energyLevelCritical");
    this.energyLevelFullyRecharged = checkInRange(energyLevelFullyRecharged,
                                                  0,
                                                  100,
                                                  "energyLevelFullyRecharged");
    this.energyLevelSufficientlyRecharged = checkInRange(energyLevelSufficientlyRecharged,
                                                         0,
                                                         100,
                                                         "energyLevelSufficientlyRecharged");
    this.maxVelocity = checkInRange(maxVelocity, 0, Integer.MAX_VALUE, "maxVelocity");
    this.maxReverseVelocity = checkInRange(maxReverseVelocity,
                                           0,
                                           Integer.MAX_VALUE,
                                           "maxReverseVelocity");
    this.rechargeOperation = requireNonNull(rechargeOperation, "rechargeOperation");
    this.procState = requireNonNull(procState, "procState");
    this.transportOrder = transportOrder;
    this.orderSequence = orderSequence;
    this.allowedOrderTypes = requireNonNull(allowedOrderTypes, "allowedOrderTypes");
    this.routeProgressIndex = routeProgressIndex;
    this.claimedResources = requireNonNull(claimedResources, "claimedResources");
    this.allocatedResources = requireNonNull(allocatedResources, "allocatedResources");
    this.state = requireNonNull(state, "state");
    this.integrationLevel = requireNonNull(integrationLevel, "integrationLevel");
    this.currentPosition = currentPosition;
    this.nextPosition = nextPosition;
    this.precisePosition = precisePosition;
    checkArgument(Double.isNaN(orientationAngle)
        || (orientationAngle >= -360.0 && orientationAngle <= 360.0),
                  "Illegal orientation angle: %s",
                  orientationAngle);
    this.orientationAngle = orientationAngle;
    this.energyLevel = checkInRange(energyLevel, 0, 100, "energyLevel");
    this.loadHandlingDevices = listWithoutNullValues(requireNonNull(loadHandlingDevices,
                                                                    "loadHandlingDevices"));
    this.layout = requireNonNull(layout, "layout");
  }

  @Override
  public Vehicle withProperty(String key, String value) {
    return new Vehicle(getName(),
                       propertiesWith(key, value),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  @Override
  public Vehicle withProperties(Map<String, String> properties) {
    return new Vehicle(getName(),
                       properties,
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  @Override
  public TCSObject<Vehicle> withHistoryEntry(ObjectHistory.Entry entry) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory().withEntryAppended(entry),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  @Override
  public TCSObject<Vehicle> withHistory(ObjectHistory history) {
    return new Vehicle(getName(),
                       getProperties(),
                       history,
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's remaining energy (in percent of the maximum).
   *
   * @return This vehicle's remaining energy.
   */
  public int getEnergyLevel() {
    return energyLevel;
  }

  /**
   * Creates a copy of this object, with the given energy level.
   *
   * @param energyLevel The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withEnergyLevel(int energyLevel) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Checks whether the vehicle's energy level is critical.
   *
   * @return <code>true</code> if, and only if, the vehicle's energy level is
   * critical.
   */
  public boolean isEnergyLevelCritical() {
    return energyLevel <= energyLevelCritical;
  }

  /**
   * Checks whether the vehicle's energy level is degraded (not <em>good</em>
   * any more).
   *
   * @return <code>true</code> if, and only if, the vehicle's energy level is
   * degraded.
   */
  public boolean isEnergyLevelDegraded() {
    return energyLevel <= energyLevelGood;
  }

  /**
   * Checks whether the vehicle's energy level is good.
   *
   * @return <code>true</code> if, and only if, the vehicle's energy level is
   * good.
   */
  public boolean isEnergyLevelGood() {
    return energyLevel > energyLevelGood;
  }

  /**
   * Checks whether the vehicle's energy level is fully recharged.
   *
   * @return <code>true</code> if, and only if, the vehicle's energy level is
   * fully recharged.
   */
  public boolean isEnergyLevelFullyRecharged() {
    return energyLevel >= energyLevelFullyRecharged;
  }

  /**
   * Checks whether the vehicle's energy level is sufficiently recharged.
   *
   * @return <code>true</code> if, and only if, the vehicle's energy level is
   * sufficiently recharged.
   */
  public boolean isEnergyLevelSufficientlyRecharged() {
    return energyLevel >= energyLevelSufficientlyRecharged;
  }

  /**
   * Returns this vehicle's critical energy level (in percent of the maximum).
   * The critical energy level is the one at/below which the vehicle should be
   * recharged.
   *
   * @return This vehicle's critical energy level.
   */
  public int getEnergyLevelCritical() {
    return energyLevelCritical;
  }

  /**
   * Creates a copy of this object, with the given critical energy level.
   *
   * @param energyLevelCritical The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withEnergyLevelCritical(int energyLevelCritical) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's good energy level (in percent of the maximum).
   * The good energy level is the one at/above which the vehicle can be
   * dispatched again when charging.
   *
   * @return This vehicle's good energy level.
   */
  public int getEnergyLevelGood() {
    return energyLevelGood;
  }

  /**
   * Creates a copy of this object, with the given good energy level.
   *
   * @param energyLevelGood The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withEnergyLevelGood(int energyLevelGood) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's energy level for being fully recharged (in percent of the maximum).
   *
   * @return This vehicle's fully recharged treshold.
   */
  public int getEnergyLevelFullyRecharged() {
    return energyLevelFullyRecharged;
  }

  /**
   * Creates a copy of this object, with the given fully recharged energy level.
   *
   * @param energyLevelFullyRecharged The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withEnergyLevelFullyRecharged(int energyLevelFullyRecharged) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's energy level for being sufficiently recharged (in percent of the
   * maximum).
   *
   * @return This vehicle's sufficiently recharged energy level.
   */
  public int getEnergyLevelSufficientlyRecharged() {
    return energyLevelSufficientlyRecharged;
  }

  /**
   * Creates a copy of this object, with the given sufficiently recharged energy level.
   *
   * @param energyLevelSufficientlyRecharged The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withEnergyLevelSufficientlyRecharged(int energyLevelSufficientlyRecharged) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the operation that the vehicle's current communication adapter
   * accepts as a command to recharge the vehicle.
   *
   * @return The operation that the vehicle's current communication adapter
   * accepts as a command to recharge the vehicle.
   */
  public String getRechargeOperation() {
    return rechargeOperation;
  }

  /**
   * Creates a copy of this object, with the given recharge operation.
   *
   * @param rechargeOperation The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withRechargeOperation(String rechargeOperation) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the current (state of the) load handling devices of this vehicle.
   *
   * @return The current (state of the) load handling devices of this vehicle.
   */
  public List<LoadHandlingDevice> getLoadHandlingDevices() {
    return loadHandlingDevices;
  }

  /**
   * Creates a copy of this object, with the given load handling devices.
   *
   * @param loadHandlingDevices The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withLoadHandlingDevices(List<LoadHandlingDevice> loadHandlingDevices) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's maximum velocity (in mm/s).
   *
   * @return This vehicle's maximum velocity (in mm/s).
   */
  public int getMaxVelocity() {
    return maxVelocity;
  }

  /**
   * Creates a copy of this object, with the given maximum velocity.
   *
   * @param maxVelocity The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withMaxVelocity(int maxVelocity) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's maximum reverse velocity (in mm/s).
   *
   * @return This vehicle's maximum reverse velocity (in mm/s).
   */
  public int getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  /**
   * Creates a copy of this object, with the given maximum reverse velocity.
   *
   * @param maxReverseVelocity The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withMaxReverseVelocity(int maxReverseVelocity) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's current state.
   *
   * @return This vehicle's current state.
   */
  public State getState() {
    return state;
  }

  /**
   * Checks if this vehicle's current state is equal to the given one.
   *
   * @param otherState The state to compare to this vehicle's one.
   * @return <code>true</code> if, and only if, the given state is equal to this
   * vehicle's one.
   */
  public boolean hasState(State otherState) {
    return state.equals(otherState);
  }

  /**
   * Creates a copy of this object, with the given state.
   *
   * @param state The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withState(State state) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's current processing state.
   *
   * @return This vehicle's current processing state.
   */
  public ProcState getProcState() {
    return procState;
  }

  /**
   * Returns this vehicle's integration level.
   *
   * @return This vehicle's integration level.
   */
  public IntegrationLevel getIntegrationLevel() {
    return integrationLevel;
  }

  /**
   * Creates a copy of this object, with the given integration level.
   *
   * @param integrationLevel The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withIntegrationLevel(IntegrationLevel integrationLevel) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Checks if this vehicle's current processing state is equal to the given
   * one.
   *
   * @param otherState The state to compare to this vehicle's one.
   * @return <code>true</code> if, and only if, the given state is equal to this
   * vehicle's one.
   */
  public boolean hasProcState(ProcState otherState) {
    return procState.equals(otherState);
  }

  /**
   * Creates a copy of this object, with the given processing state.
   *
   * @param procState The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withProcState(ProcState procState) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns this vehicle's current length.
   *
   * @return this vehicle's current length.
   */
  public int getLength() {
    return length;
  }

  /**
   * Creates a copy of this object, with the given length.
   *
   * @param length The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withLength(int length) {
    checkInRange(length, 1, Integer.MAX_VALUE, "length");
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns a reference to the transport order this vehicle is currently
   * processing.
   *
   * @return A reference to the transport order this vehicle is currently
   * processing, or <code>null</code>, if it is not processing any transport
   * order at the moment.
   */
  public TCSObjectReference<TransportOrder> getTransportOrder() {
    return transportOrder;
  }

  /**
   * Creates a copy of this object, with the given transport order.
   *
   * @param transportOrder The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withTransportOrder(TCSObjectReference<TransportOrder> transportOrder) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns a reference to the order sequence this vehicle is currently
   * processing.
   *
   * @return A reference to the order sequence this vehicle is currently
   * processing, or <code>null</code>, if it is not processing any order
   * sequence at the moment.
   */
  public TCSObjectReference<OrderSequence> getOrderSequence() {
    return orderSequence;
  }

  /**
   * Creates a copy of this object, with the given order sequence.
   *
   * @param orderSequence The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withOrderSequence(TCSObjectReference<OrderSequence> orderSequence) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the set of order types this vehicle is allowed to process.
   *
   * @return The set of order types this vehicle is allowed to process.
   */
  public Set<String> getAllowedOrderTypes() {
    return allowedOrderTypes;
  }

  /**
   * Creates a copy of this object, with the given set of allowed order types.
   *
   * @param allowedOrderTypes The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withAllowedOrderTypes(Set<String> allowedOrderTypes) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the index of the last route step travelled for the current drive
   * order of the current transport order.
   *
   * @return The index of the last route step travelled for the current drive
   * order of the current transport order.
   */
  public int getRouteProgressIndex() {
    return routeProgressIndex;
  }

  /**
   * Creates a copy of this object, with the given route progress index.
   *
   * @param routeProgressIndex The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withRouteProgressIndex(int routeProgressIndex) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the resources this vehicle has claimed for future allocation.
   *
   * @return The resources this vehicle has claimed for future allocation.
   */
  public List<Set<TCSResourceReference<?>>> getClaimedResources() {
    return claimedResources;
  }

  /**
   * Creates a copy of this object, with the given claimed resources.
   *
   * @param claimedResources The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withClaimedResources(List<Set<TCSResourceReference<?>>> claimedResources) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the resources this vehicle has allocated.
   *
   * @return The resources this vehicle has allocated.
   */
  public List<Set<TCSResourceReference<?>>> getAllocatedResources() {
    return allocatedResources;
  }

  /**
   * Creates a copy of this object, with the given allocated resources.
   *
   * @param allocatedResources The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withAllocatedResources(List<Set<TCSResourceReference<?>>> allocatedResources) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns a reference to the point this vehicle currently occupies.
   *
   * @return A reference to the point this vehicle currently occupies, or
   * <code>null</code>, if this vehicle's position is unknown or the vehicle is
   * currently not in the system.
   */
  public TCSObjectReference<Point> getCurrentPosition() {
    return currentPosition;
  }

  /**
   * Creates a copy of this object, with the given current position.
   *
   * @param currentPosition The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withCurrentPosition(TCSObjectReference<Point> currentPosition) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns a reference to the point this vehicle is expected to be seen at
   * next.
   *
   * @return A reference to the point this vehicle is expected to be seen at
   * next, or <code>null</code>, if this vehicle's next position is unknown.
   */
  public TCSObjectReference<Point> getNextPosition() {
    return nextPosition;
  }

  /**
   * Creates a copy of this object, with the given next position.
   *
   * @param nextPosition The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withNextPosition(TCSObjectReference<Point> nextPosition) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the vehicle's position in world coordinates [mm], independent
   * from logical positions/point names. May be <code>null</code> if the vehicle
   * hasn't provided a precise position.
   *
   * @return The vehicle's precise position in mm.
   */
  public Triple getPrecisePosition() {
    return precisePosition;
  }

  /**
   * Creates a copy of this object, with the given precise position.
   *
   * @param precisePosition The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withPrecisePosition(Triple precisePosition) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the vehicle's current orientation angle (-360..360).
   * May be <code>Double.NaN</code> if the vehicle hasn't provided an
   * orientation angle.
   *
   * @return The vehicle's current orientation angle.
   */
  public double getOrientationAngle() {
    return orientationAngle;
  }

  /**
   * Creates a copy of this object, with the given orientation angle.
   *
   * @param orientationAngle The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withOrientationAngle(double orientationAngle) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Returns the information regarding the grahical representation of this vehicle.
   *
   * @return The information regarding the grahical representation of this vehicle.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Vehicle withLayout(Layout layout) {
    return new Vehicle(getName(),
                       getProperties(),
                       getHistory(),
                       length,
                       energyLevelGood,
                       energyLevelCritical,
                       energyLevelFullyRecharged,
                       energyLevelSufficientlyRecharged,
                       maxVelocity,
                       maxReverseVelocity,
                       rechargeOperation,
                       procState,
                       transportOrder,
                       orderSequence,
                       allowedOrderTypes,
                       routeProgressIndex,
                       claimedResources,
                       allocatedResources,
                       state,
                       integrationLevel,
                       currentPosition,
                       nextPosition,
                       precisePosition,
                       orientationAngle,
                       energyLevel,
                       loadHandlingDevices,
                       layout);
  }

  /**
   * Checks if this vehicle is currently processing any transport order.
   *
   * @return <code>true</code> if, and only if, this vehicle is currently
   * processing a transport order.
   */
  public boolean isProcessingOrder() {
    return transportOrder != null;
  }

  @Override
  public String toString() {
    return "Vehicle{"
        + "name=" + getName()
        + ", procState=" + procState
        + ", integrationLevel=" + integrationLevel
        + ", state=" + state
        + ", energyLevel=" + energyLevel
        + ", currentPosition=" + currentPosition
        + ", precisePosition=" + precisePosition
        + ", orientationAngle=" + orientationAngle
        + ", nextPosition=" + nextPosition
        + ", loadHandlingDevices=" + loadHandlingDevices
        + ", length=" + length
        + ", transportOrder=" + transportOrder
        + ", routeProgressIndex=" + routeProgressIndex
        + ", claimedResources=" + claimedResources
        + ", allocatedResources=" + allocatedResources
        + ", orderSequence=" + orderSequence
        + ", energyLevelGood=" + energyLevelGood
        + ", energyLevelCritical=" + energyLevelCritical
        + ", energyLevelFullyRecharged=" + energyLevelFullyRecharged
        + ", energyLevelSufficientlyRecharged=" + energyLevelSufficientlyRecharged
        + ", maxVelocity=" + maxVelocity
        + ", maxReverseVelocity=" + maxReverseVelocity
        + ", rechargeOperation=" + rechargeOperation
        + ", allowedOrderTypes=" + allowedOrderTypes
        + '}';
  }

  /**
   * The elements of this enumeration describe the various possible states of a
   * vehicle.
   */
  public enum State {

    /**
     * The vehicle's current state is unknown, e.g. because communication with
     * it is currently not possible for some reason.
     */
    UNKNOWN,
    /**
     * The vehicle's state is known and it's not in an error state, but it is
     * not available for receiving orders.
     */
    UNAVAILABLE,
    /**
     * There is a problem with the vehicle.
     */
    ERROR,
    /**
     * The vehicle is currently idle/available for processing movement orders.
     */
    IDLE,
    /**
     * The vehicle is processing a movement order.
     */
    EXECUTING,
    /**
     * The vehicle is currently recharging its battery/refilling fuel.
     */
    CHARGING
  }

  /**
   * A vehicle's state of integration into the system.
   */
  public static enum IntegrationLevel {

    /**
     * The vehicle's reported position is ignored.
     */
    TO_BE_IGNORED,
    /**
     * The vehicle's reported position is noticed, meaning that resources will not be reserved for
     * it.
     */
    TO_BE_NOTICED,
    /**
     * The vehicle's reported position is respected, meaning that resources will be reserved for it.
     */
    TO_BE_RESPECTED,
    /**
     * The vehicle is fully integrated and may be assigned to transport orders.
     */
    TO_BE_UTILIZED
  }

  /**
   * A vehicle's processing state as seen by the dispatcher.
   */
  public enum ProcState {

    /**
     * The vehicle is currently not processing a transport order.
     */
    IDLE,
    /**
     * The vehicle is currently processing a transport order and is waiting for
     * the next drive order to be assigned to it.
     */
    AWAITING_ORDER,
    /**
     * The vehicle is currently processing a drive order.
     */
    PROCESSING_ORDER
  }

  /**
   * The elements of this enumeration represent the possible orientations of a
   * vehicle.
   */
  public enum Orientation {

    /**
     * Indicates that the vehicle is driving/standing oriented towards its
     * front.
     */
    FORWARD,
    /**
     * Indicates that the vehicle is driving/standing oriented towards its
     * back.
     */
    BACKWARD,
    /**
     * Indicates that the vehicle's orientation is undefined/unknown.
     */
    UNDEFINED
  }

  /**
   * Contains information regarding the grahical representation of a vehicle.
   */
  public static class Layout
      implements Serializable {

    /**
     * The color in which vehicle routes are to be emphasized.
     */
    private final Color routeColor;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(Color.RED);
    }

    /**
     * Creates a new instance.
     *
     * @param routeColor The color in which vehicle routes are to be emphasized.
     */
    public Layout(Color routeColor) {
      this.routeColor = requireNonNull(routeColor, "routeColor");
    }

    /**
     * Returns the color in which vehicle routes are to be emphasized.
     *
     * @return The color in which vehicle routes are to be emphasized.
     */
    public Color getRouteColor() {
      return routeColor;
    }

    /**
     * Creates a copy of this object, with the given color.
     *
     * @param routeColor The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withRouteColor(Color routeColor) {
      return new Layout(routeColor);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/VehicleCommAdapterPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.management;

import javax.swing.JPanel;

/**
 * A base class for panels associated with comm adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class VehicleCommAdapterPanel
    extends JPanel {

  /**
   * Returns the title for this comm adapter panel.
   * The default implementation returns the accessible name from the panel's accessible context.
   *
   * @return The title for this comm adapter panel.
   */
  public String getTitle() {
    return getAccessibleContext().getAccessibleName();
  }

  /**
   * Notifies a comm adapter panel that the corresponding process model changed.
   * The comm adapter panel may want to update the content its representing.
   *
   * @param attributeChanged The attribute name that chagend.
   * @param processModel The process model.
   */
  public abstract void processModelChange(String attributeChanged,
                                          VehicleProcessModelTO processModel);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/util/PlantOverviewModelingApplicationConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import org.opentcs.components.plantoverview.LocationTheme;
import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the PlantOverview application (in modeling mode).
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(PlantOverviewModelingApplicationConfiguration.PREFIX)
public interface PlantOverviewModelingApplicationConfiguration {
  
  /**
   * This configuration's prefix.
   */
  String PREFIX = "plantoverviewapp";

  @ConfigurationEntry(
      type = "String",
      description = {"The plant overview application's locale, as a BCP 47 language tag.",
                     "Examples: 'en', 'de', 'zh'"},
      orderKey = "0_init_0")
  String locale();

  @ConfigurationEntry(
      type = "Class name",
      description = {
        "The name of the class to be used for the location theme.",
        "Must be a class extending org.opentcs.components.plantoverview.LocationTheme"
      },
      orderKey = "3_themes_0"
  )
  Class<? extends LocationTheme> locationThemeClass();
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/components/tree/elements/TreeElementsInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;

/**
 * A Guice module for this package.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TreeElementsInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {
    install(new FactoryModuleBuilder()
        .implement(VehicleUserObject.class, VehicleUserObjectOperating.class)
        .build(UserObjectFactory.class));
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/Colors.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.awt.Color;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;

/**
 * Provides utilty methods for working with colors.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Colors {

  /**
   * Prevents instantiation of this utility class.
   */
  private Colors() {
  }

  /**
   * Returns a hexadecimal representation of the given color in the RGB color space.
   * <p>
   * The pattern of the strings returned by this method is {@code "#RRGGBB"}.
   * </p>
   *
   * @param color The color to be encoded.
   * @return The representation of the given color.
   */
  @Nonnull
  public static String encodeToHexRGB(@Nonnull Color color) {
    requireNonNull(color, "color");

    return String.format("#%06X", color.getRGB() & 0x00FFFFFF);
  }

  /**
   * Returns a {@code Color} instance described by the given hexadecimal representation.
   *
   * @param rgbHex The hexadecimal representation of the color to be returned in the RGB color
   * space.
   *
   * @return A {@code Color} instance described by the given value.
   * @throws NumberFormatException If the given string cannot be parsed.
   */
  @Nonnull
  public static Color decodeFromHexRGB(@Nonnull String rgbHex)
      throws NumberFormatException {
    requireNonNull(rgbHex, "rgbHex");

    return Color.decode(rgbHex);
  }

}


<|start_filename|>openTCS-KernelControlCenter/src/test/java/org/opentcs/kernelcontrolcenter/KernelControlCenterApplicationTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter;

import org.junit.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.opentcs.common.PortalManager;
import org.opentcs.kernelcontrolcenter.exchange.KernelEventFetcher;
import org.opentcs.kernelcontrolcenter.util.KernelControlCenterConfiguration;
import org.opentcs.util.event.EventBus;

/**
 * Test cases for the {@link KernelControlCenterApplication}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class KernelControlCenterApplicationTest {

  /**
   * The class to test.
   */
  private KernelControlCenterApplication application;

  /**
   * The event bus for online events.
   */
  private EventBus eventBus;

  /**
   * The portal manager to establish kernel connections.
   */
  private PortalManager portalManager;

  /**
   * The control center gui.
   */
  private KernelControlCenter controlCenter;

  /**
   * The configuration of the control center.
   */
  private KernelControlCenterConfiguration configuration;

  @Before
  public void setUp() {
    eventBus = mock(EventBus.class);
    portalManager = mock(PortalManager.class);
    configuration = mock(KernelControlCenterConfiguration.class);
    controlCenter = mock(KernelControlCenter.class);
    application = spy(new KernelControlCenterApplication(mock(KernelEventFetcher.class),
                                                         controlCenter,
                                                         portalManager,
                                                         eventBus,
                                                         configuration));
  }

  @Test
  public void onlyInitializeOnce() {
    when(configuration.connectAutomaticallyOnStartup()).thenReturn(true);
    application.initialize();
    application.initialize();

    Assert.assertTrue("Control center is not initialized", application.isInitialized());
    verify(controlCenter, times(1)).initialize();
    verify(portalManager, times(1)).connect(any());
    verify(application, times(1)).online(anyBoolean());
  }

  @Test
  public void onlyTerminateOnce() {
    when(configuration.connectAutomaticallyOnStartup()).thenReturn(false);
    application.initialize();
    application.terminate();
    application.terminate();

    Assert.assertFalse("Control center is initialized", application.isInitialized());
    verify(controlCenter, times(1)).terminate();
    verify(application, times(1)).offline();
  }

  @Test
  public void shouldOnlyConnectOnce() {
    //When trying to connect, return the value that indicates a successful connection
    when(portalManager.connect(any())).thenReturn(true);
    application.initialize();
    application.online(true);
    application.online(true);

    Assert.assertTrue("Control center is not initialized", application.isInitialized());
    Assert.assertTrue("Control center is not online", application.isOnline());
    verify(controlCenter, times(1)).initialize();
    verify(portalManager, times(1)).connect(any());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/VehicleCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.awt.Color;
import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import static org.opentcs.util.Assertions.checkArgument;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * A transfer object describing a block in the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The vehicle's length (in mm).
   */
  private int length = 1000;
  /**
   * The energy level value at/below which the vehicle should be recharged.
   */
  private int energyLevelCritical = 30;
  /**
   * The energy level value at/above which the vehicle can be dispatched again when charging.
   */
  private int energyLevelGood = 90;
  /**
   * The energy level value at/above which the vehicle is considered fully recharged.
   */
  private int energyLevelFullyRecharged = 90;
  /**
   * The energy level value at/above which the vehicle is considered sufficiently recharged.
   */
  private int energyLevelSufficientlyRecharged = 30;
  /**
   * The vehicle's maximum velocity (in mm/s).
   */
  private int maxVelocity = 1000;
  /**
   * The vehicle's maximum reverse velocity (in mm/s).
   */
  private int maxReverseVelocity = 1000;
  /**
   * The information regarding the grahical representation of this vehicle.
   */
  private Layout layout = new Layout();

  /**
   * Creates a new instance.
   *
   * @param name The name of this vehicle.
   */
  public VehicleCreationTO(@Nonnull String name) {
    super(name);
  }

  private VehicleCreationTO(@Nonnull String name,
                            @Nonnull Map<String, String> properties,
                            int length,
                            int energyLevelCritical,
                            int energyLevelGood,
                            int energyLevelFullyRecharged,
                            int energyLevelSufficientlyRecharged,
                            int maxVelocity,
                            int maxReverseVelocity,
                            @Nonnull Layout layout) {
    super(name, properties);
    this.length = length;
    this.energyLevelCritical = energyLevelCritical;
    this.energyLevelGood = energyLevelGood;
    this.energyLevelFullyRecharged = energyLevelFullyRecharged;
    this.energyLevelSufficientlyRecharged = energyLevelSufficientlyRecharged;
    this.maxVelocity = maxVelocity;
    this.maxReverseVelocity = maxReverseVelocity;
    this.layout = requireNonNull(layout, "layout");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new instance.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public VehicleCreationTO withName(@Nonnull String name) {
    return new VehicleCreationTO(name,
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public VehicleCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new VehicleCreationTO(getName(),
                                 properties,
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public VehicleCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new VehicleCreationTO(getName(),
                                 propertiesWith(key, value),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Returns the vehicle's length (in mm).
   *
   * @return The vehicle's length (in mm).
   */
  public int getLength() {
    return length;
  }

  /**
   * Creates a copy of this object with the vehicle's given length (in mm).
   *
   * @param length The new length. Must be at least 1.
   * @return A copy of this object, differing in the given vehicle length.
   */
  public VehicleCreationTO withLength(int length) {
    checkArgument(length >= 1, "length must be at least 1: " + length);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Returns this vehicle's critical energy level (in percent of the maximum).
   * The critical energy level is the one at/below which the vehicle should be recharged.
   *
   * @return This vehicle's critical energy level.
   */
  public int getEnergyLevelCritical() {
    return energyLevelCritical;
  }

  /**
   * Creates a copy of this object with the given critical energy level.
   * The critical energy level is the one at/below which the vehicle should be recharged.
   *
   * @param energyLevelCritical The new critical energy level. Must not be smaller than 0 or
   * greater than 100.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withEnergyLevelCritical(int energyLevelCritical) {
    checkInRange(energyLevelCritical, 0, 100);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Returns this vehicle's good energy level (in percent of the maximum).
   * The good energy level is the one at/above which the vehicle can be dispatched again when
   * charging.
   *
   * @return This vehicle's good energy level.
   */
  public int getEnergyLevelGood() {
    return energyLevelGood;
  }

  /**
   * Creates a copy of this object with the vehicle's good energy level (in percent of the maximum).
   * The good energy level is the one at/above which the vehicle can be dispatched again when
   * charging.
   *
   * @param energyLevelGood The new good energy level. Must not be smaller than 0 or greater than
   * 100.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withEnergyLevelGood(int energyLevelGood) {
    checkInRange(energyLevelGood, 0, 100);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Returns this vehicle's fully recharged energy level (in percent of the maximum).
   *
   * @return This vehicle's fully recharged energy level.
   */
  public int getEnergyLevelFullyRecharged() {
    return energyLevelFullyRecharged;
  }

  /**
   * Creates a copy of this object with the vehicle's fully recharged energy level (in percent of
   * the maximum).
   *
   * @param energyLevelFullyRecharged The new fully recharged energy level.
   * Must not be smaller than 0 or greater than 100.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withEnergyLevelFullyRecharged(int energyLevelFullyRecharged) {
    checkInRange(energyLevelFullyRecharged, 0, 100);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Returns this vehicle's sufficiently recharged energy level (in percent of the maximum).
   *
   * @return This vehicle's sufficiently recharged energy level.
   */
  public int getEnergyLevelSufficientlyRecharged() {
    return energyLevelSufficientlyRecharged;
  }

  /**
   * Creates a copy of this object with the vehicle's sufficiently recharged energy level (in
   * percent of the maximum).
   *
   * @param energyLevelSufficientlyRecharged The new sufficiently recharged energy level.
   * Must not be smaller than 0 or greater than 100.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withEnergyLevelSufficientlyRecharged(
      int energyLevelSufficientlyRecharged) {
    checkInRange(energyLevelSufficientlyRecharged, 0, 100);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  public int getMaxVelocity() {
    return maxVelocity;
  }

  /**
   * Creates a copy of this object with the given maximum velocity (in mm/s).
   *
   * @param maxVelocity the new max velocity.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withMaxVelocity(int maxVelocity) {
    this.maxVelocity = checkInRange(maxVelocity, 0, Integer.MAX_VALUE);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  public int getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  /**
   * Creates a copy of this object with the given maximum reverse velocity (in mm/s).
   *
   * @param maxReverseVelocity the new maximum reverse velocity.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withMaxReverseVelocity(int maxReverseVelocity) {
    checkInRange(maxReverseVelocity, 0, Integer.MAX_VALUE);
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  /**
   * Returns the information regarding the grahical representation of this vehicle.
   *
   * @return The information regarding the grahical representation of this vehicle.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public VehicleCreationTO withLayout(Layout layout) {
    return new VehicleCreationTO(getName(),
                                 getModifiableProperties(),
                                 length,
                                 energyLevelCritical,
                                 energyLevelGood,
                                 energyLevelFullyRecharged,
                                 energyLevelSufficientlyRecharged,
                                 maxVelocity,
                                 maxReverseVelocity,
                                 layout);
  }

  @Override
  public String toString() {
    return "VehicleCreationTO{"
        + "name=" + getName()
        + ", length=" + length
        + ", energyLevelCritical=" + energyLevelCritical
        + ", energyLevelGood=" + energyLevelGood
        + ", energyLevelFullyRecharged=" + energyLevelFullyRecharged
        + ", energyLevelSufficientlyRecharged=" + energyLevelSufficientlyRecharged
        + ", maxVelocity=" + maxVelocity
        + ", maxReverseVelocity=" + maxReverseVelocity
        + ", layout=" + layout
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Contains information regarding the grahical representation of a vehicle.
   */
  public static class Layout
      implements Serializable {

    /**
     * The color in which vehicle routes are to be emphasized.
     */
    private final Color routeColor;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(Color.RED);
    }

    /**
     * Creates a new instance.
     *
     * @param routeColor The color in which vehicle routes are to be emphasized.
     */
    public Layout(Color routeColor) {
      this.routeColor = requireNonNull(routeColor, "routeColor");
    }

    /**
     * Returns the color in which vehicle routes are to be emphasized.
     *
     * @return The color in which vehicle routes are to be emphasized.
     */
    public Color getRouteColor() {
      return routeColor;
    }

    /**
     * Creates a copy of this object, with the given color.
     *
     * @param routeColor The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withRouteColor(Color routeColor) {
      return new Layout(routeColor);
    }

    @Override
    public String toString() {
      return "Layout{"
          + "routeColor=" + routeColor
          + '}';
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/Path.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralOperation;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * Describes a connection between two {@link Point}s which a {@link Vehicle} may traverse.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Path
    extends TCSResource<Path>
    implements Serializable {

  /**
   * A reference to the point which this point originates in.
   */
  private final TCSObjectReference<Point> sourcePoint;
  /**
   * A reference to the point which this point ends in.
   */
  private final TCSObjectReference<Point> destinationPoint;
  /**
   * The length of this path (in mm).
   */
  private final long length;
  /**
   * The absolute maximum allowed forward velocity on this path (in mm/s).
   * A value of 0 (default) means forward movement is not allowed on this path.
   */
  private final int maxVelocity;
  /**
   * The absolute maximum allowed reverse velocity on this path (in mm/s).
   * A value of 0 (default) means reverse movement is not allowed on this path.
   */
  private final int maxReverseVelocity;
  /**
   * The peripheral operations to be performed when a vehicle travels along this path.
   */
  private final List<PeripheralOperation> peripheralOperations;
  /**
   * A flag for marking this path as locked (i.e. to prevent vehicles from using it).
   */
  private final boolean locked;
  /**
   * The information regarding the grahical representation of this path.
   */
  private final Layout layout;

  /**
   * Creates a new Path.
   *
   * @param name The new path's name.
   * @param sourcePoint A reference to this path's starting point.
   * @param destinationPoint A reference to this path's destination point.
   */
  public Path(String name,
              TCSObjectReference<Point> sourcePoint,
              TCSObjectReference<Point> destinationPoint) {
    super(name);
    this.sourcePoint = requireNonNull(sourcePoint, "sourcePoint");
    this.destinationPoint = requireNonNull(destinationPoint, "destinationPoint");
    this.length = 1;
    this.maxVelocity = 1000;
    this.maxReverseVelocity = 1000;
    this.peripheralOperations = new ArrayList<>();
    this.locked = false;
    this.layout = new Layout();
  }

  private Path(String name,
               Map<String, String> properties,
               ObjectHistory history,
               TCSObjectReference<Point> sourcePoint,
               TCSObjectReference<Point> destinationPoint,
               long length,
               int maxVelocity,
               int maxReverseVelocity,
               List<PeripheralOperation> peripheralOperations,
               boolean locked,
               Layout layout) {
    super(name, properties, history);
    this.sourcePoint = requireNonNull(sourcePoint, "sourcePoint");
    this.destinationPoint = requireNonNull(destinationPoint, "destinationPoint");
    this.length = checkInRange(length, 1, Long.MAX_VALUE, "length");
    this.maxVelocity = checkInRange(maxVelocity, 0, Integer.MAX_VALUE, "maxVelocity");
    this.maxReverseVelocity = checkInRange(maxReverseVelocity,
                                           0,
                                           Integer.MAX_VALUE,
                                           "maxReverseVelocity");
    this.peripheralOperations = new ArrayList<>(requireNonNull(peripheralOperations,
                                                               "peripheralOperations"));
    this.locked = locked;
    this.layout = requireNonNull(layout, "layout");
  }

  @Override
  public Path withProperty(String key, String value) {
    return new Path(getName(),
                    propertiesWith(key, value),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  @Override
  public Path withProperties(Map<String, String> properties) {
    return new Path(getName(),
                    properties,
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  @Override
  public TCSObject<Path> withHistoryEntry(ObjectHistory.Entry entry) {
    return new Path(getName(),
                    getProperties(),
                    getHistory().withEntryAppended(entry),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  @Override
  public TCSObject<Path> withHistory(ObjectHistory history) {
    return new Path(getName(),
                    getProperties(),
                    history,
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Return the length of this path (in mm).
   *
   * @return The length of this path (in mm).
   */
  public long getLength() {
    return length;
  }

  /**
   * Creates a copy of this object, with the given length.
   *
   * @param length The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Path withLength(long length) {
    return new Path(getName(),
                    getProperties(),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Returns a reference to the point which this path originates in.
   *
   * @return A reference to the point which this path originates in.
   */
  public TCSObjectReference<Point> getSourcePoint() {
    return sourcePoint;
  }

  /**
   * Returns a reference to the point which this path ends in.
   *
   * @return A reference to the point which this path ends in.
   */
  public TCSObjectReference<Point> getDestinationPoint() {
    return destinationPoint;
  }

  /**
   * Return the maximum allowed forward velocity (in mm/s) for this path.
   *
   * @return The maximum allowed forward velocity (in mm/s). A value of 0 means
   * forward movement is not allowed on this path.
   */
  public int getMaxVelocity() {
    return maxVelocity;
  }

  /**
   * Creates a copy of this object, with the given maximum velocity.
   *
   * @param maxVelocity The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Path withMaxVelocity(int maxVelocity) {
    return new Path(getName(),
                    getProperties(),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Return the maximum allowed reverse velocity (in mm/s) for this path.
   *
   * @return The maximum allowed reverse velocity (in mm/s). A value of 0 means
   * reverse movement is not allowed on this path.
   */
  public int getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  /**
   * Creates a copy of this object, with the given maximum reverse velocity.
   *
   * @param maxReverseVelocity The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Path withMaxReverseVelocity(int maxReverseVelocity) {
    return new Path(getName(),
                    getProperties(),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Returns the peripheral operations to be performed when a vehicle travels along this path.
   *
   * @return The peripheral operations to be performed when a vehicle travels along this path.
   */
  public List<PeripheralOperation> getPeripheralOperations() {
    return Collections.unmodifiableList(peripheralOperations);
  }

  /**
   * Creates a copy of this object, with the given peripheral operations.
   *
   * @param peripheralOperations The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Path withPeripheralOperations(@Nonnull List<PeripheralOperation> peripheralOperations) {
    return new Path(getName(),
                    getProperties(),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Return the lock status of this path (i.e. whether this path my be used by
   * vehicles or not).
   *
   * @return <code>true</code> if this path is currently locked (i.e. it may not
   * be used by vehicles), else <code>false</code>.
   */
  public boolean isLocked() {
    return locked;
  }

  /**
   * Creates a copy of this object, with the given locked flag.
   *
   * @param locked The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Path withLocked(boolean locked) {
    return new Path(getName(),
                    getProperties(),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Returns the information regarding the grahical representation of this path.
   *
   * @return The information regarding the grahical representation of this path.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Path withLayout(Layout layout) {
    return new Path(getName(),
                    getProperties(),
                    getHistory(),
                    sourcePoint,
                    destinationPoint,
                    length,
                    maxVelocity,
                    maxReverseVelocity,
                    peripheralOperations,
                    locked,
                    layout);
  }

  /**
   * Checks whether this path is navigable in forward direction.
   *
   * @return <code>true</code> if, and only if, this path is not locked and its
   * maximum forward velocity is not zero.
   */
  public boolean isNavigableForward() {
    return !locked && maxVelocity != 0;
  }

  /**
   * Checks whether this path is navigable in backward/reverse direction.
   *
   * @return <code>true</code> if, and only if, this path is not locked and its
   * maximum reverse velocity is not zero.
   */
  public boolean isNavigableReverse() {
    return !locked && maxReverseVelocity != 0;
  }

  /**
   * Checks whether this path is navigable towards the given point.
   *
   * @param navPoint The point.
   * @return If <code>navPoint</code> is this path's destination point, returns
   * <code>isNavigableForward()</code>; if <code>navPoint</code> is this path's
   * source point, returns <code>isNavigableReverse()</code>.
   * @throws IllegalArgumentException If the given point is neither the source
   * point nor the destination point of this path.
   */
  public boolean isNavigableTo(TCSObjectReference<Point> navPoint)
      throws IllegalArgumentException {
    if (Objects.equals(navPoint, destinationPoint)) {
      return isNavigableForward();
    }
    else if (Objects.equals(navPoint, sourcePoint)) {
      return isNavigableReverse();
    }
    else {
      throw new IllegalArgumentException(navPoint + " is not an end point of " + this);
    }
  }

  /**
   * Contains information regarding the grahical representation of a path.
   */
  public static class Layout
      implements Serializable {

    /**
     * The connection type the path is represented as.
     */
    private final ConnectionType connectionType;
    /**
     * Control points describing the way the path is drawn (if the connection type
     * is {@link ConnectionType#BEZIER}, {@link ConnectionType#BEZIER_3}
     * or {@link ConnectionType#POLYPATH}).
     */
    private final List<Couple> controlPoints;
    /**
     * The ID of the layer on which the path is to be drawn.
     */
    private final int layerId;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(ConnectionType.DIRECT, new ArrayList<>(), 0);
    }

    /**
     * Creates a new instance.
     *
     * @param connectionType The connection type a path is represented as.
     * @param controlPoints Control points describing the way the path is drawn.
     * @param layerId The ID of the layer on which the path is to be drawn.
     */
    public Layout(ConnectionType connectionType, List<Couple> controlPoints, int layerId) {
      this.connectionType = connectionType;
      this.controlPoints = requireNonNull(controlPoints, "controlPoints");
      this.layerId = layerId;
    }

    /**
     * Returns the connection type the path is represented as.
     *
     * @return The connection type the path is represented as.
     */
    public ConnectionType getConnectionType() {
      return connectionType;
    }

    /**
     * Creates a copy of this object, with the given connection type.
     *
     * @param connectionType The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withConnectionType(ConnectionType connectionType) {
      return new Layout(connectionType, controlPoints, layerId);
    }

    /**
     * Returns the control points describing the way the path is drawn.
     * Returns an empty list if connection type is not {@link ConnectionType#BEZIER},
     * {@link ConnectionType#BEZIER_3} or {@link ConnectionType#POLYPATH}.
     *
     * @return The control points describing the way the path is drawn.
     */
    public List<Couple> getControlPoints() {
      return Collections.unmodifiableList(controlPoints);
    }

    /**
     * Creates a copy of this object, with the given control points.
     *
     * @param controlPoints The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withControlPoints(List<Couple> controlPoints) {
      return new Layout(connectionType, controlPoints, layerId);
    }

    /**
     * Returns the ID of the layer on which the path is to be drawn.
     *
     * @return The layer ID.
     */
    public int getLayerId() {
      return layerId;
    }

    /**
     * Creates a copy of this object, with the given layer ID.
     *
     * @param layerId The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLayer(int layerId) {
      return new Layout(connectionType, controlPoints, layerId);
    }

    /**
     * The connection type a path is represented as.
     */
    public static enum ConnectionType {

      /**
       * A direct connection.
       */
      DIRECT,
      /**
       * An elbow connection.
       */
      ELBOW,
      /**
       * A slanted connection.
       */
      SLANTED,
      /**
       * A polygon path with any number of vertecies.
       */
      POLYPATH,
      /**
       * A bezier curve with 2 control points.
       */
      BEZIER,
      /**
       * A bezier curve with 3 control points.
       */
      BEZIER_3;
    }
  }
}


<|start_filename|>openTCS-API-Injection/src/main/java/org/opentcs/customizations/ConfigurableInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.customizations;

import com.google.inject.AbstractModule;

/**
 * A base class for Guice modules adding or customizing bindings for the kernel application and the
 * plant overview application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class ConfigurableInjectionModule
    extends AbstractModule {

  /**
   * A provider for configuration bindings.
   */
  private org.opentcs.configuration.ConfigurationBindingProvider configBindingProvider;

  /**
   * Returns the configuration bindung provider.
   *
   * @return The configuration binding provider.
   */
  public org.opentcs.configuration.ConfigurationBindingProvider getConfigBindingProvider() {
    return configBindingProvider;
  }

  /**
   * Sets the configuration binding provider.
   *
   * @param configBindingProvider The new configuration binding provider.
   */
  public void setConfigBindingProvider(
      org.opentcs.configuration.ConfigurationBindingProvider configBindingProvider) {
    this.configBindingProvider = configBindingProvider;
  }
}


<|start_filename|>openTCS-PlantOverview-Themes-Default/src/main/java/org/opentcs/guing/plugins/themes/StatelessImageVehicleTheme.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.themes;

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import static java.util.Objects.requireNonNull;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import org.opentcs.components.plantoverview.VehicleTheme;
import org.opentcs.data.model.Vehicle;

/**
 * An implementation of <code>VehicleTheme</code> using a single image, disregarding vehicles'
 * states.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class StatelessImageVehicleTheme
    implements VehicleTheme {

  /**
   * The single image used for representing vehicles, regardless of their state.
   */
  private final Image image;
  /**
   * The path containing the images.
   */
  private static final String PATH = "/org/opentcs/guing/plugins/themes/symbols/vehicle/Vehicle24.png";

  public StatelessImageVehicleTheme() {
    this.image = loadImage(PATH);
  }

  @Override
  public Image statelessImage(Vehicle vehicle) {
    return image;
  }

  @Override
  public Image statefulImage(Vehicle vehicle) {
    return image;
  }

  /**
   * Loads an image from the file with the given name.
   *
   * @param fileName The name of the file from which to load the image.
   * @return The image.
   */
  private Image loadImage(String fileName) {
    requireNonNull(fileName, "fileName");

    URL url = getClass().getResource(fileName);
    if (url == null) {
      throw new IllegalArgumentException("Invalid image file name " + fileName);
    }
    try {
      return ImageIO.read(url);
    }
    catch (IOException exc) {
      throw new IllegalArgumentException("Exception loading image", exc);
    }
  }

  @Override
  public String label(Vehicle vehicle) {
    String name = vehicle.getName();

    // Find digits.
    Pattern p = Pattern.compile("\\d+");
    Matcher m = p.matcher(name);

    // If at least one group of digits was found, use the first one.
    if (m.find()) {
      return m.group();
    }

    return name;
  }

  @Override
  public int labelOffsetX() {
    return -8;
  }

  @Override
  public int labelOffsetY() {
    return 5;
  }

  @Override
  public Color labelColor() {
    return Color.BLUE;
  }

  @Override
  public Font labelFont() {
    return new Font("Arial", Font.BOLD, 12);
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralCommAdapterPanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanel;
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanelFactory;

/**
 * A factory for creating {@link LoopbackPeripheralCommAdapterPanel} instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralCommAdapterPanelFactory
    implements PeripheralCommAdapterPanelFactory {

  /**
   * The panel components factory to use.
   */
  private final LoopbackPeripheralAdapterPanelComponentsFactory panelComponentsFactory;
  /**
   * Indicates whether this component is initialized or not.
   */
  private boolean initialized;

  @Inject
  public LoopbackPeripheralCommAdapterPanelFactory(
      LoopbackPeripheralAdapterPanelComponentsFactory panelComponentsFactory) {
    this.panelComponentsFactory = requireNonNull(panelComponentsFactory, "panelComponentsFactory");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    initialized = false;
  }

  @Override
  public List<PeripheralCommAdapterPanel> getPanelsFor(
      @Nonnull PeripheralCommAdapterDescription description,
      @Nonnull TCSResourceReference<Location> location,
      @Nonnull PeripheralProcessModel processModel) {
    requireNonNull(description, "description");
    requireNonNull(location, "location");
    requireNonNull(processModel, "processModel");

    if (!providesPanelsFor(description, processModel)) {
      return new LinkedList<>();
    }

    return Arrays.asList(panelComponentsFactory
        .createPanel((LoopbackPeripheralProcessModel) processModel));
  }

  private boolean providesPanelsFor(PeripheralCommAdapterDescription description,
                                    PeripheralProcessModel processModel) {
    return (description instanceof LoopbackPeripheralCommAdapterDescription)
        && (processModel instanceof LoopbackPeripheralProcessModel);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/thirdparty/components/drawing/OpenTCSDrawingViewOperating.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 *
 * Extended by IML: 1. Show Blocks and Pathes as overlay 2. Switch labels on/off
 *
 * @(#)DefaultDrawingView.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.components.drawing;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.jhotdraw.draw.DefaultDrawingView;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.components.drawing.figures.OriginFigure;
import org.opentcs.guing.components.drawing.figures.VehicleFigure;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.thirdparty.jhotdraw.components.drawing.AbstractOpenTCSDrawingView;

/**
 * A DrawingView implementation for the openTCS plant overview.
 *
 */
public class OpenTCSDrawingViewOperating
    extends AbstractOpenTCSDrawingView {

  /**
   * Contains the vehicle on the drawing, for which transport order shall be drawn.
   */
  private final List<VehicleModel> fVehicles = new ArrayList<>();
  /**
   * The vehicle the view should highlight and follow.
   */
  private VehicleModel fFocusVehicle;

  /**
   * Creates new instance.
   *
   * @param appState Stores the application's current state.
   * @param modelManager Provides the current system model.
   */
  @Inject
  public OpenTCSDrawingViewOperating(ApplicationState appState, ModelManager modelManager) {
    super(appState, modelManager);
  }

  @Override
  public void removeAll() {
    fVehicles.clear();
    super.removeAll();
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    super.propertyChange(evt);

    if (evt.getPropertyName().equals(VehicleFigure.POSITION_CHANGED)) {
      scrollTo((VehicleFigure) getModelManager().getModel().getFigure(fFocusVehicle));
    }
  }

  @Override
  public void cutSelectedItems() {
  }

  @Override
  public void copySelectedItems() {
  }

  @Override
  public void pasteBufferedItems() {
  }

  @Override
  public void delete() {
  }

  @Override
  public void duplicate() {
  }

  @Override
  public void displayDriveOrders(VehicleModel vehicle, boolean visible) {
    requireNonNull(vehicle, "vehicle");

    if (visible) {
      if (!fVehicles.contains(vehicle)) {
        fVehicles.add(vehicle);
      }
    }
    else {
      fVehicles.remove(vehicle);
    }
  }

  @Override
  public void followVehicle(@Nonnull final VehicleModel model) {
    requireNonNull(model, "model");

    stopFollowVehicle();
    fFocusVehicle = model;
    fFocusVehicle.setViewFollows(true);
    VehicleFigure vFigure = (VehicleFigure) getModelManager().getModel().getFigure(fFocusVehicle);
    if (vFigure != null) {
      vFigure.addPropertyChangeListener(this);
      scrollTo(vFigure);
    }
  }

  @Override
  public void stopFollowVehicle() {
    if (fFocusVehicle == null) {
      return;
    }

    fFocusVehicle.setViewFollows(false);
    VehicleFigure vFigure = (VehicleFigure) getModelManager().getModel().getFigure(fFocusVehicle);
    if (vFigure != null) {
      vFigure.removePropertyChangeListener(this);
    }
    fFocusVehicle = null;
    repaint();
  }

  @Override
  public void setBlocks(ModelComponent blocks) {
  }
 
  @Override
  protected void drawTool(Graphics2D g2d) {
    super.drawTool(g2d);

    if (getEditor() == null || getEditor().getTool() == null || getEditor().getActiveView() != this) {
      return;
    }

    if (fFocusVehicle != null) {
      // Set focus on the selected vehicle and its destination point
      highlightVehicle(g2d);
    }
    else {
      // Set focus on the selected figure
      highlightFocus(g2d);
    }
  }

  @Override
  protected DefaultDrawingView.EventHandler createEventHandler() {
    return new ExtendedEventHandler();
  }

  @Override
  protected Rectangle2D.Double computeBounds(Figure figure) {
    Rectangle2D.Double bounds = super.computeBounds(figure);

    if (figure instanceof VehicleFigure) {
      // Also show the target point
      VehicleModel vehicleModel = ((VehicleFigure) figure).getModel();
      PointModel pointModel = vehicleModel.getNextPoint();

      if (pointModel != null) {
        Figure pointFigure = getModelManager().getModel().getFigure(pointModel);
        bounds.add(pointFigure.getBounds());
      }
    }

    return bounds;
  }

  @Override
  public void delete(Set<ModelComponent> components) {
  }

  /**
   * Sets a radial gradient for the vehicle, its current and next position.
   *
   * @param g2d
   */
  private void highlightVehicle(Graphics2D g2d) {
    if (fFocusVehicle == null) {
      return;
    }

    final Figure currentVehicleFigure = getModelManager().getModel().getFigure(fFocusVehicle);
    if (currentVehicleFigure == null) {
      return;
    }

    Rectangle2D.Double bounds = currentVehicleFigure.getBounds();
    double xCenter = bounds.getCenterX();
    double yCenter = bounds.getCenterY();
    Point2D.Double pCenterView = new Point2D.Double(xCenter, yCenter);
    Point pCenterDrawing = drawingToView(pCenterView);

    // radial gradient for the vehicle
    Point2D center
        = new Point2D.Float((float) pCenterDrawing.x, (float) pCenterDrawing.y);
    float radius = 30;
    float[] dist = {0.0f, 0.7f, 0.8f, 1.0f};
    Color[] colors = {
      new Color(1.0f, 1.0f, 1.0f, 0.0f), // Focus: 100% transparent
      new Color(1.0f, 1.0f, 1.0f, 0.0f),
      new Color(1.0f, 0.0f, 0.0f, 0.7f), // Circle: red
      new Color(0f, 0f, 0f, 0f) // Background
    };
    RadialGradientPaint paint
        = new RadialGradientPaint(center, radius, dist, colors,
                                  MultipleGradientPaint.CycleMethod.NO_CYCLE);

    Graphics2D gVehicle = (Graphics2D) g2d.create();
    gVehicle.setPaint(paint);
    gVehicle.fillRect(0, 0, getWidth(), getHeight());
    gVehicle.dispose();

    // radial gradient for the next position
    PointModel pointModel = fFocusVehicle.getNextPoint();

    if (pointModel != null) {
      Figure nextPoint = getModelManager().getModel().getFigure(pointModel);
      bounds = nextPoint.getBounds();
      xCenter = bounds.getCenterX();
      yCenter = bounds.getCenterY();
      pCenterView = new Point2D.Double(xCenter, yCenter);
      pCenterDrawing = drawingToView(pCenterView);
      center = new Point2D.Float((float) pCenterDrawing.x, (float) pCenterDrawing.y);

      radius = 20;
      Color[] colorsGreen = {
        new Color(1.0f, 1.0f, 1.0f, 0.0f), // Focus: 100% transparent
        new Color(1.0f, 1.0f, 1.0f, 0.0f),
        new Color(0.0f, 1.0f, 0.0f, 0.7f), // Circle: green
        new Color(0f, 0f, 0f, 0f) // Background
      };
      paint = new RadialGradientPaint(center, radius, dist, colorsGreen,
                                      MultipleGradientPaint.CycleMethod.NO_CYCLE);

      Graphics2D gNextPosition = (Graphics2D) g2d.create();
      gNextPosition.setPaint(paint);
      gNextPosition.fillRect(0, 0, getWidth(), getHeight());
      gNextPosition.dispose();
    }

    // radial gradient for last position
    pointModel = fFocusVehicle.getPoint();

    if (pointModel != null && fFocusVehicle.getPrecisePosition() != null) {
      Figure lastPoint = getModelManager().getModel().getFigure(pointModel);
      bounds = lastPoint.getBounds();
      xCenter = bounds.getCenterX();
      yCenter = bounds.getCenterY();
      pCenterView = new Point2D.Double(xCenter, yCenter);
      pCenterDrawing = drawingToView(pCenterView);
      center = new Point2D.Float((float) pCenterDrawing.x, (float) pCenterDrawing.y);

      radius = 20;
      Color[] colorsBlue = {
        new Color(1.0f, 1.0f, 1.0f, 0.0f), // Focus: 100% transparent
        new Color(1.0f, 1.0f, 1.0f, 0.0f),
        new Color(0.0f, 0.0f, 1.0f, 0.7f), // Circle: blue
        new Color(0f, 0f, 0f, 0f) // Background
      };
      paint = new RadialGradientPaint(center, radius, dist, colorsBlue,
                                      MultipleGradientPaint.CycleMethod.NO_CYCLE);

      Graphics2D gCurrentPosition = (Graphics2D) g2d.create();
      gCurrentPosition.setPaint(paint);
      gCurrentPosition.fillRect(0, 0, getWidth(), getHeight());
      gCurrentPosition.dispose();
    }

    // After drawing the RadialGradientPaint the drawing area needs to
    // repainted, otherwise the GradientPaint isn't drawn correctly or
    // the old one isn't removed. We make sure the repaint() call doesn't
    // end in an infinite loop.
    loopProofRepaintDrawingArea();
  }

  private class ExtendedEventHandler
      extends AbstractExtendedEventHandler {

    @Override
    protected boolean shouldShowFigure(Figure figure) {
      return !(figure instanceof VehicleFigure) && !(figure instanceof OriginFigure);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/VehicleController.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.util.ExplainedBoolean;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * Provides high-level methods for the kernel to control a vehicle.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleController
    extends Lifecycle,
            Scheduler.Client {

  /**
   * Sets/Updates the current transport order for the vehicle associated with this controller.
   * <p>
   * The controller is expected to process the transport order's current drive order.
   * Once processing of this drive order is finished, it sets the vehicle's processing state to
   * {@link Vehicle.ProcState#AWAITING_ORDER} to signal this.
   * This method will then be called for either the next drive order in the same transport order or
   * a new transport order.
   * </p>
   * <p>
   * This method may also be called again for the same/current drive order in case <em>any</em>
   * future part of the route to be taken for the transport order has changed.
   * In case of such an update, the continuity of the transport order's route is guaranteed, which
   * means that the previously given route and the one given in {@code newOrder} match up to the
   * last point already sent to the vehicle associated with this controller.
   * Beyond that point the routes may diverge.
   * </p>
   *
   * @param newOrder The new or updated transport order.
   * @throws IllegalArgumentException If {@code newOrder} cannot be processed for some reason, e.g.
   * because it has already been partly processed and the route's continuity is not given.
   */
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default void setTransportOrder(@Nonnull TransportOrder newOrder)
      throws IllegalArgumentException {
  }

  /**
   * Sets the current drive order for the vehicle associated with this
   * controller.
   *
   * @param newOrder The new drive order.
   * @param orderProperties Properties of the transport order the new drive
   * order is part of.
   * @throws IllegalStateException If this controller already has a drive order.
   * @deprecated Use {@link #setTransportOrder(org.opentcs.data.order.TransportOrder)} instead.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void setDriveOrder(@Nonnull DriveOrder newOrder,
                             @Nonnull Map<String, String> orderProperties)
      throws IllegalStateException {
  }

  /**
   * Updates the current drive order for the vehicle associated with this controller.
   * <p>
   * An update is only allowed, if the continuity of the current drive order is guaranteed.
   * The continuity of the current drive order is guaranteed, if the routes of both the current
   * drive order and the {@code newOrder} match to the point where the vehicle associated with this
   * controller is currently reported at. Beyond that point the routes may diverge.
   * </p>
   *
   * @param newOrder The new drive order.
   * @param orderProperties Properties of the transport order the new drive order is part of.
   * @throws IllegalStateException If the {@code newOrder} would not guarantee the current drive
   * order's continuity.
   * @deprecated Use {@link #setTransportOrder(org.opentcs.data.order.TransportOrder)} instead.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void updateDriveOrder(@Nonnull DriveOrder newOrder,
                                @Nonnull Map<String, String> orderProperties)
      throws IllegalStateException {
  }

  /**
   * Notifies the controller that the current transport order is to be aborted.
   * After receiving this notification, the controller should not send any further movement commands
   * to the vehicle.
   *
   * @param immediate If <code>true</code>, immediately reset the current transport order for the
   * vehicle associated with this controller, clears the vehicle's command queue implicitly and
   * frees all resources reserved for the removed commands/movements.
   * (Note that this is unsafe, as the vehicle might be moving and clearing the command queue might
   * overlap with the vehicle's movement/progress.)
   */
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default void abortTransportOrder(boolean immediate) {
    if (immediate) {
      clearDriveOrder();
    }
    else {
      abortDriveOrder();
    }
  }

  /**
   * Resets the current drive order for the vehicle associated with this controller.
   * At the end of this method, {@link #clearCommandQueue()} is called implicitly.
   *
   * @deprecated Use {@link #abortTransportOrder(boolean)} instead.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void clearDriveOrder() {
  }

  /**
   * Notifies the controller that the current drive order is to be aborted.
   * After receiving this notification, the controller should not send any
   * further movement commands to the vehicle.
   *
   * @deprecated Use {@link #abortTransportOrder(boolean)} instead.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void abortDriveOrder() {
  }

  /**
   * Clears the associated vehicle's command queue and frees all resources reserved for the removed
   * commands/movements.
   *
   * @deprecated Use {@link #abortTransportOrder(boolean)} instead.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void clearCommandQueue() {
  }

  /**
   * Checks if the vehicle would be able to process the given transport order, taking into account
   * its current state.
   *
   * @param order The transport order to be checked.
   * @return An <code>ExplainedBoolean</code> indicating whether the vehicle would be able to
   * process given order.
   */
  @Nonnull
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default ExplainedBoolean canProcess(@Nonnull TransportOrder order) {
    return canProcess(
        order.getFutureDriveOrders().stream()
            .map(driveOrder -> driveOrder.getDestination().getOperation())
            .collect(Collectors.toList())
    );
  }

  /**
   * Checks if the vehicle would be able to process the given sequence of operations, taking into
   * account its current state.
   *
   * @param operations A sequence of operations that might appear in future commands.
   * @return An <code>ExplainedBoolean</code> indicating whether the vehicle would be able to
   * process every single operation in the list (in the given order).
   * @deprecated Use {@link #canProcess(org.opentcs.data.order.TransportOrder)} instead.
   */
  @Nonnull
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default ExplainedBoolean canProcess(@Nonnull List<String> operations) {
    return new ExplainedBoolean(false, "VehicleController default implementation");
  }

  /**
   * Delivers a generic message to the communication adapter.
   *
   * @param message The message to be delivered.
   */
  void sendCommAdapterMessage(@Nullable Object message);

  /**
   * Sends a {@link AdapterCommand} to the communication adapter.
   *
   * @param command The adapter command to be sent.
   */
  void sendCommAdapterCommand(@Nonnull AdapterCommand command);

  /**
   * Returns a list of {@link MovementCommand}s that have been sent to the communication adapter.
   *
   * @return A list of {@link MovementCommand}s that have been sent to the communication adapter.
   */
  @Nonnull
  Queue<MovementCommand> getCommandsSent();

  /**
   * Returns the command for which the execution of peripheral operations must be completed before
   * it can be sent to the communication adapter.
   * For this command, allocated resources have already been accepted.
   *
   * @return The command for which the execution of peripheral operations is pending or
   * {@link Optional#empty()} if there's no such command.
   */
  @Nonnull
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default Optional<MovementCommand> getInteractionsPendingCommand() {
    return Optional.empty();
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/AbstractModelAttribute.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.opentcs.guing.model.ModelComponent;

/**
 * Attribute of a {@link ModelComponent}.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class AbstractModelAttribute
    implements ModelAttribute {

  /**
   * The model this attribute is attached to.
   */
  private ModelComponent fModel;
  /**
   * Indicates that this attribute has changed.
   */
  private ChangeState fChangeState = ChangeState.NOT_CHANGED;
  /**
   * Description of this attribute.
   */
  private String fDescription = "";
  /**
   * Tooltip text.
   */
  private String fHelptext = "";
  /**
   * Indicates whether or not this attribute can simultaneously be edited with other
   * attributes of the same name of other model components.
   */
  private boolean fCollectiveEditable;
  /**
   * Indicates whether or not this attribute can be changed in modeling mode.
   */
  private boolean fModellingEditable = true;
  /**
   * Indicates whether or not this attribute can be changed in operating mode.
   */
  private boolean fOperatingEditable;

  /**
   * Creates a new instance.
   *
   * @param model The model component.
   */
  public AbstractModelAttribute(ModelComponent model) {
    fModel = model;
  }

  @Override // ModelAttribute
  public ModelComponent getModel() {
    return fModel;
  }

  @Override // ModelAttribute
  public void setModel(ModelComponent model) {
    fModel = model;
  }

  @Override // ModelAttribute
  public void markChanged() {
    fChangeState = ChangeState.CHANGED;
  }

  @Override // ModelAttribute
  public void unmarkChanged() {
    fChangeState = ChangeState.NOT_CHANGED;
  }

  @Override // ModelAttribute
  public void setChangeState(ChangeState state) {
    fChangeState = state;
  }

  /**
   * Returns the change state of this attribute.
   * @return The change state.
   */
  public ChangeState getChangeState() {
    return fChangeState;
  }

  @Override // ModelAttribute
  public boolean hasChanged() {
    return (fChangeState != ChangeState.NOT_CHANGED);
  }

  @Override // ModelAttribute
  public void setDescription(String description) {
    fDescription = description;
  }

  @Override // ModelAttribute
  public String getDescription() {
    return fDescription;
  }

  @Override // ModelAttribute
  public void setHelptext(String helptext) {
    fHelptext = helptext;
  }

  @Override // ModelAttribute
  public String getHelptext() {
    return fHelptext;
  }

  @Override // ModelAttribute
  public void setCollectiveEditable(boolean collectiveEditable) {
    fCollectiveEditable = collectiveEditable;
  }

  @Override // ModelAttribute
  public boolean isCollectiveEditable() {
    return fCollectiveEditable;
  }

  @Override // ModelAttribute
  public void setModellingEditable(boolean editable) {
    fModellingEditable = editable;
  }

  @Override // ModelAttribute
  public boolean isModellingEditable() {
    return fModellingEditable;
  }

  @Override // ModelAttribute
  public void setOperatingEditable(boolean editable) {
    fOperatingEditable = editable;
  }

  @Override // ModelAttribute
  public boolean isOperatingEditable() {
    return fOperatingEditable;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/OpenTCSDrawingEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
import org.jhotdraw.draw.DefaultDrawingEditor;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.action.IncreaseHandleDetailLevelAction;
import org.jhotdraw.draw.event.CompositeFigureEvent;
import org.jhotdraw.draw.event.CompositeFigureListener;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.drawing.figures.OffsetFigure;
import org.opentcs.guing.components.drawing.figures.TCSLabelFigure;
import org.opentcs.guing.event.DrawingEditorEvent;
import org.opentcs.guing.event.DrawingEditorListener;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.util.CourseObjectFactory;
import org.opentcs.thirdparty.jhotdraw.application.action.draw.MoveAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.DeleteAction;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.SelectAllAction;
import org.opentcs.util.event.EventHandler;

/**
 * The <code>DrawingEditor</code> coordinates <code>DrawingViews</code>
 * and the <code>Drawing</code>.
 * It also offers methods to add specific unique figures to the
 * <code>Drawing</code>.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSDrawingEditor
    extends DefaultDrawingEditor
    implements EventHandler {

  /**
   * Width on the screen edge.
   */
  private static final int MARGIN = 20;
  /**
   * A factory for course objects.
   */
  private final CourseObjectFactory crsObjectFactory;
  /**
   *
   */
  private final CompositeFigureEventHandler cmpFigureEvtHandler = new CompositeFigureEventHandler();
  /**
   * Listens for figure selection, addition or removal events.
   */
  private final List<DrawingEditorListener> fDrawingEditorListeners = new ArrayList<>();
  /**
   * The drawing that contains all figures.
   */
  private Drawing fDrawing;
  // These invisible figures are moved automatically to enlarge the drawing.
  private OffsetFigure topOffsetFigure;
  private OffsetFigure bottomOffsetFigure;
  private OffsetFigure rightOffsetFigure;
  private OffsetFigure leftOffsetFigure;

  /**
   * Creates a new instance.
   *
   * @param crsObjFactory A factory for course objects.
   */
  @Inject
  public OpenTCSDrawingEditor(CourseObjectFactory crsObjFactory) {
    this.crsObjectFactory = requireNonNull(crsObjFactory, "crsObjectFactory");
  }

  @Override
  public void onEvent(Object event) {
  }

  /**
   * Creates the offset figures, sets their position to the current bounds of the
   * view and repaints the ruler to fit the current grid.
   */
  public void initializeViewport() {
    initializeRuler();
    removeOffsetFigures();
    topOffsetFigure = crsObjectFactory.createOffsetFigure();
    bottomOffsetFigure = crsObjectFactory.createOffsetFigure();
    leftOffsetFigure = crsObjectFactory.createOffsetFigure();
    rightOffsetFigure = crsObjectFactory.createOffsetFigure();

    OpenTCSDrawingView activeView = getActiveView();
    if (activeView == null) {
      return;
    }

    // Rectangle that contains all figures
    Rectangle2D.Double drawingArea = getDrawing().getDrawingArea();
    // The visible rectangle
    Rectangle visibleRect = activeView.getComponent().getVisibleRect();
    // The size of the invisible offset figures
    double wFigure = topOffsetFigure.getBounds().width;
    double hFigure = topOffsetFigure.getBounds().height;

    // When the drawing already contains figures
    double xLeft = drawingArea.x;
    double xRight = drawingArea.x + drawingArea.width;
    double yTop = drawingArea.y;
    double yBottom = drawingArea.y + drawingArea.height;

    // An empty drawing only contains the origin figure, which shall be
    // on the bottom left 
    if (visibleRect.width > drawingArea.width && visibleRect.height > drawingArea.height) {
      xLeft = -drawingArea.width / 2 - MARGIN;
      xRight = visibleRect.width + xLeft - (MARGIN + wFigure / 2);
      yBottom = -(-drawingArea.height / 2 - MARGIN);
      yTop = -(visibleRect.height - yBottom - (MARGIN + hFigure / 2));
    }

    double xCenter = (xLeft + xRight) / 2;
    double yCenter = (yBottom + yTop) / 2;

    topOffsetFigure.setBounds(new Point2D.Double(xCenter, yTop), null);
    bottomOffsetFigure.setBounds(new Point2D.Double(xCenter, yBottom), null);
    leftOffsetFigure.setBounds(new Point2D.Double(xLeft, yCenter), null);
    rightOffsetFigure.setBounds(new Point2D.Double(xRight, yCenter), null);

    getDrawing().add(topOffsetFigure);
    getDrawing().add(bottomOffsetFigure);
    getDrawing().add(leftOffsetFigure);
    getDrawing().add(rightOffsetFigure);

    // XXX Do we still need to call this?
    activeView.setScaleFactor(activeView.getScaleFactor());
//    validateViewTranslation();
  }

  protected CourseObjectFactory getCourseObjectFactory() {
    return crsObjectFactory;
  }

  private void initializeRuler() {
    OpenTCSDrawingView activeView = getActiveView();
    DrawingViewScrollPane scrollPane
        = (DrawingViewScrollPane) activeView.getComponent().getParent().getParent();
    Rectangle2D.Double drawingArea
        = activeView.getDrawing().getDrawingArea();
    scrollPane.getHorizontalRuler().setPreferredWidth((int) drawingArea.width);
    scrollPane.getVerticalRuler().setPreferredHeight((int) drawingArea.height);
  }

  /**
   * Removes the <code>OffsetFigure</code>s off the drawing.
   */
  private void removeOffsetFigures() {
    if (getDrawing() == null) {
      return;
    }

    getDrawing().remove(topOffsetFigure);
    getDrawing().remove(bottomOffsetFigure);
    getDrawing().remove(leftOffsetFigure);
    getDrawing().remove(rightOffsetFigure);
  }

  /**
   * Adds a listener.
   *
   * @param listener The listener.
   */
  public void addDrawingEditorListener(DrawingEditorListener listener) {
    requireNonNull(listener, "listener");
    fDrawingEditorListeners.add(listener);
  }

  /**
   * Removes a listener.
   *
   * @param listener The listener.
   */
  public void removeDrawingEditorListener(DrawingEditorListener listener) {
    requireNonNull(listener, "listener");
    fDrawingEditorListeners.remove(listener);
  }

  /**
   * Sets the system model.
   *
   * @param systemModel The model of the course.
   */
  public void setSystemModel(SystemModel systemModel) {
    setDrawing(systemModel.getDrawing());
    for (DrawingView drawView : getDrawingViews()) {
      ((OpenTCSDrawingView) drawView).setBlocks(
          systemModel.getMainFolder(SystemModel.FolderKey.BLOCKS)
      );
    }
  }

  public Drawing getDrawing() {
    return fDrawing;
  }

  public void setDrawing(Drawing drawing) {
    requireNonNull(drawing, "drawing");

    if (fDrawing != null) {
      fDrawing.removeCompositeFigureListener(cmpFigureEvtHandler);
    }
    fDrawing = drawing;
    fDrawing.addCompositeFigureListener(cmpFigureEvtHandler);

    // Also let the drawing views know about the new drawing.
    for (DrawingView view : getDrawingViews()) {
      view.setDrawing(drawing);
    }
  }

  @Override
  public void add(DrawingView view) {
    super.add(view);
    view.setDrawing(fDrawing);
  }

  @Override
  public OpenTCSDrawingView getActiveView() {
    return (OpenTCSDrawingView) super.getActiveView();
  }

  public Collection<OpenTCSDrawingView> getAllViews() {
    Collection<OpenTCSDrawingView> result = new LinkedList<>();
    for (DrawingView view : getDrawingViews()) {
      result.add((OpenTCSDrawingView) view);
    }
    return result;
  }

  /**
   * Notification of the <code>DrawingView</code> that a figure was added.
   *
   * @param figure The added figure.
   */
  public void figureAdded(Figure figure) {
    // Create the data model to a new point or location figure and show
    // the name in the label
    if (figure instanceof LabeledFigure) {
      LabeledFigure labeledFigure = (LabeledFigure) figure;

      if (labeledFigure.getLabel() == null) {
        // Create the label and add the figure to the data model
        TCSLabelFigure label = new TCSLabelFigure();
        Point2D.Double pos = labeledFigure.getStartPoint();
        pos.x += label.getOffset().x;
        pos.y += label.getOffset().y;
        label.setBounds(pos, pos);
        labeledFigure.setLabel(label);
      }
    }

    for (DrawingEditorListener listener : fDrawingEditorListeners) {
      listener.figureAdded(new DrawingEditorEvent(this, figure));
    }
  }

  /**
   * Notification of the <code>DrawingView</code> that a figure was removed.
   *
   * @param figure The figure that was removed.
   */
  public void figureRemoved(Figure figure) {
    for (DrawingEditorListener listener : fDrawingEditorListeners) {
      listener.figureRemoved(new DrawingEditorEvent(this, figure));
    }
  }

  /**
   * Notification of the <code>DrawingView</code> that figures were selected.
   *
   * @param figures The selected figures.
   */
  public void figuresSelected(List<Figure> figures) {
    for (DrawingEditorListener listener : fDrawingEditorListeners) {
      listener.figureSelected(new DrawingEditorEvent(this, figures));
    }
  }

  /**
   * Overrides the method from DefaultDrawingEditor to create a tool-specific
   * input map.
   * The implementation of this class creates an input map for the following
   * action ID's:
   * - DeleteAction
   * - MoveAction.West, .East, .North, .South
   *
   * SelectAll, Cut, Copy, Paste are handled by SelectAllAction etc.
   *
   * @return The input map.
   */
  @Override  // DefaultDrawingEditor
  protected InputMap createInputMap() {
    InputMap m = new InputMap();

    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), DeleteAction.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), DeleteAction.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), MoveAction.West.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), MoveAction.East.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), MoveAction.North.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), MoveAction.South.ID);

    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK), MoveAction.West.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK), MoveAction.East.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK), MoveAction.North.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK), MoveAction.South.ID);

    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.SHIFT_DOWN_MASK), MoveAction.West.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_DOWN_MASK), MoveAction.East.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.SHIFT_DOWN_MASK), MoveAction.North.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_DOWN_MASK), MoveAction.South.ID);

    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK), MoveAction.West.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK), MoveAction.East.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK), MoveAction.North.ID);
    m.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK), MoveAction.South.ID);

    return m;
  }

  @Override  // DefaultDrawingEditor
  protected ActionMap createActionMap() {
    ActionMap m = new ActionMap();

    m.put(DeleteAction.ID, new DeleteAction());
    m.put(SelectAllAction.ID, new SelectAllAction());
    m.put(IncreaseHandleDetailLevelAction.ID, new IncreaseHandleDetailLevelAction(this));

    m.put(MoveAction.East.ID, new MoveAction.East(this));
    m.put(MoveAction.West.ID, new MoveAction.West(this));
    m.put(MoveAction.North.ID, new MoveAction.North(this));
    m.put(MoveAction.South.ID, new MoveAction.South(this));

//    m.put(CutAction.ID, new CutAction());
//    m.put(CopyAction.ID, new CopyAction());
//    m.put(PasteAction.ID, new PasteAction());
    return m;
  }

  private class CompositeFigureEventHandler
      implements CompositeFigureListener {

    /**
     * Creates a new instance.
     */
    public CompositeFigureEventHandler() {
    }

    @Override
    public void figureAdded(CompositeFigureEvent e) {
      OpenTCSDrawingEditor.this.figureAdded(e.getChildFigure());
    }

    @Override
    public void figureRemoved(CompositeFigureEvent e) {
      OpenTCSDrawingEditor.this.figureRemoved(e.getChildFigure());
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/vehicles/IsParkable.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.vehicles;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.selection.ParkVehicleSelectionFilter;

/**
 * Filters vehicles that are parkable.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class IsParkable
    implements ParkVehicleSelectionFilter {

  /**
   * The object service.
   */
  private final TCSObjectService objectService;

  /**
   * Creates a new instance.
   *
   * @param objectService The object service.
   */
  @Inject
  public IsParkable(TCSObjectService objectService) {
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public Collection<String> apply(Vehicle vehicle) {
    return parkable(vehicle) ? new ArrayList<>() : Arrays.asList(getClass().getName());
  }

  private boolean parkable(Vehicle vehicle) {
    return vehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_UTILIZED
        && vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && vehicle.hasState(Vehicle.State.IDLE)
        && !isParkingPosition(vehicle.getCurrentPosition())
        && vehicle.getOrderSequence() == null;
  }

  private boolean isParkingPosition(TCSObjectReference<Point> positionRef) {
    if (positionRef == null) {
      return false;
    }

    Point position = objectService.fetchObject(Point.class, positionRef);
    return position.isParkingPosition();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/DefaultLayerManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.swing.SwingUtilities;
import org.jhotdraw.draw.Drawing;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.application.ViewManager;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.guing.model.DrawnModelComponent;
import org.opentcs.guing.model.SystemModel;
import static org.opentcs.util.Assertions.checkArgument;
import org.opentcs.util.event.EventBus;

/**
 * The default implementation of {@link LayerManager}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultLayerManager
    implements LayerManager,
               LayerGroupManager {

  /**
   * The sets of model components mapped to the IDs of the layers the model components are drawn on.
   */
  private final Map<Integer, Set<DrawnModelComponent>> components = new HashMap<>();
  /**
   * The view manager.
   */
  private final ViewManager viewManager;
  /**
   * The application's event bus.
   */
  private final EventBus eventBus;
  /**
   * The listeners for layer group data changes.
   */
  private final Set<LayerGroupChangeListener> layerGroupChangeListeners = new HashSet<>();
  /**
   * The listener for layer data changes.
   */
  private LayerChangeListener layerChangeListener;
  /**
   * The system model we're working with.
   */
  private SystemModel systemModel;
  /**
   * Whether this instance is initialized or not.
   */
  private boolean initialized;

  @Inject
  public DefaultLayerManager(ViewManager viewManager, @ApplicationEventBus EventBus eventBus) {
    this.viewManager = requireNonNull(viewManager, "viewManager");
    this.eventBus = requireNonNull(eventBus, "eventBus");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventBus.subscribe(this);

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventBus.unsubscribe(this);

    initialized = false;
  }

  @Override
  public void setLayerChangeListener(LayerChangeListener listener) {
    layerChangeListener = listener;
  }

  @Override
  public void setLayerVisible(int layerId, boolean visible) {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    LayerWrapper wrapper = getLayerWrapper(layerId);
    // We want to  manipulate the drawing (by adding or removing figures) only if the visible state
    // of the layer has actually changed. This prevents figures from being added multiple times and
    // figures from being removed although they are no longer present in the drawing.
    if (wrapper.getLayer().isVisible() == visible) {
      return;
    }

    boolean visibleBefore = wrapper.getLayer().isVisible() && wrapper.getLayerGroup().isVisible();
    Layer oldLayer = wrapper.getLayer();
    Layer newLayer = oldLayer.withVisible(visible);
    wrapper.setLayer(newLayer);
    boolean visibleAfter = wrapper.getLayer().isVisible() && wrapper.getLayerGroup().isVisible();

    if (visibleBefore != visibleAfter) {
      layerVisibilityChanged(newLayer, visibleAfter);
    }

    layerChangeListener.layersChanged();
  }

  @Override
  public void setLayerName(int layerId, String name) {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    LayerWrapper wrapper = getLayerWrapper(layerId);
    Layer oldLayer = wrapper.getLayer();
    Layer newLayer = oldLayer.withName(name);
    wrapper.setLayer(newLayer);

    layerChangeListener.layersChanged();
  }

  @Override
  public void onEvent(Object event) {
    if (!(event instanceof SystemModelTransitionEvent)) {
      return;
    }

    SystemModelTransitionEvent evt = (SystemModelTransitionEvent) event;
    switch (evt.getStage()) {
      case UNLOADED:
        reset();
        break;
      case LOADED:
        systemModel = evt.getModel();
        restoreLayers();
        break;
      default: // Do nothing.
    }
  }

  @Override
  public void addLayerGroupChangeListener(LayerGroupChangeListener listener) {
    layerGroupChangeListeners.add(listener);
  }

  @Override
  public boolean containsComponents(int layerId) {
    return !components.getOrDefault(layerId, new HashSet<>()).isEmpty();
  }

  @Override
  public void setGroupVisible(int groupId, boolean visible) {
    checkArgument(getLayerGroup(groupId) != null,
                  "A layer group with layer group ID '%d' doesn't exist.",
                  groupId);

    LayerGroup oldGroup = getLayerGroup(groupId);
    if (oldGroup.isVisible() == visible) {
      return;
    }

    Map<Boolean, List<LayerWrapper>> wrappersByLayerVisibility
        = getLayerWrappers().values().stream()
            .filter(wrapper -> wrapper.getLayer().getGroupId() == groupId)
            .collect(Collectors.partitioningBy(wrapper -> wrapper.getLayer().isVisible()));

    // We only need to take care of "visible" layers. Non-visible layers are not affected by 
    // any changes to a group's visibility.
    for (LayerWrapper wrapper : wrappersByLayerVisibility.get(Boolean.TRUE)) {
      if (wrapper.getLayerGroup().isVisible() != visible) {
        layerVisibilityChanged(wrapper.getLayer(), visible);
      }
    }

    // Update the group for all layer wrappers that are assigned to it.
    LayerGroup newGroup = oldGroup.withVisible(visible);
    getLayerWrappers().values().stream()
        .filter(wrapper -> wrapper.getLayer().getGroupId() == groupId)
        .forEach(wrapper -> wrapper.setLayerGroup(newGroup));

    // Update the group in the system model's layout.
    getLayerGroups().put(groupId, newGroup);

    notifyGroupsChanged();
  }

  @Override
  public void setGroupName(int groupId, String name) {
    checkArgument(getLayerGroup(groupId) != null,
                  "A layer group with layer group ID '%d' doesn't exist.",
                  groupId);

    LayerGroup oldGroup = getLayerGroup(groupId);
    LayerGroup newGroup = oldGroup.withName(name);

    // Update the group for all layer wrappers that are assigned to it.
    getLayerWrappers().values().stream()
        .filter(wrapper -> wrapper.getLayer().getGroupId() == groupId)
        .forEach(wrapper -> wrapper.setLayerGroup(newGroup));

    // Update the group in the system model's layout.
    getLayerGroups().put(groupId, newGroup);

    notifyGroupsChanged();
    layerChangeListener.layersChanged();
  }

  protected void reset() {
    components.clear();
  }

  protected void restoreLayers() {
    restoreComponentsMap();

    notifyGroupsInitialized();
    layerChangeListener.layersInitialized();
  }

  protected LayerChangeListener getLayerChangeListener() {
    return layerChangeListener;
  }

  /**
   * Returns the system model the layer manager is working with.
   *
   * @return The system model.
   */
  protected SystemModel getSystemModel() {
    return systemModel;
  }

  /**
   * Returns the model components mapped to the IDs of the layers they are drawn on.
   *
   * @return The model components.
   */
  protected Map<Integer, Set<DrawnModelComponent>> getComponents() {
    return components;
  }

  /**
   * Returns the view manager the layer manager is working with.
   *
   * @return The view manager.
   */
  protected ViewManager getViewManager() {
    return viewManager;
  }

  /**
   * Returns the set of drawings the layer manager is working with.
   *
   * @return The set of drawings the layer manager is working with.
   */
  protected Set<Drawing> getDrawings() {
    return viewManager.getDrawingViewMap().values().stream()
        .map(scrollPane -> scrollPane.getDrawingView().getDrawing())
        .collect(Collectors.toSet());
  }

  /**
   * Maps the given model component to the given layer ID.
   *
   * @param modelComponent The model component to add.
   * @param layerId The ID of the layer to map the model component to.
   * @see #getComponents()
   */
  protected void addComponent(DrawnModelComponent modelComponent, int layerId) {
    components.get(layerId).add(modelComponent);
  }

  /**
   * Removes the mapping for the given model component.
   *
   * @param modelComponent The model component to remove.
   * @see #getComponents()
   */
  protected void removeComponent(DrawnModelComponent modelComponent) {
    LayerWrapper layerWrapper = modelComponent.getPropertyLayerWrapper().getValue();
    components.get(layerWrapper.getLayer().getId()).remove(modelComponent);
  }

  /**
   * Returns the layer wrappers in the system model's layout.
   *
   * @return The layer wrappers in the system model's layout.
   */
  protected Map<Integer, LayerWrapper> getLayerWrappers() {
    return systemModel.getLayoutModel().getPropertyLayerWrappers().getValue();
  }

  /**
   * Returns the layer wrapper for the given layer ID.
   *
   * @param layerId The layer ID.
   * @return The layer wrapper.
   */
  protected LayerWrapper getLayerWrapper(int layerId) {
    return getLayerWrappers().get(layerId);
  }

  /**
   * Returns the layer groups in the system model's layout.
   *
   * @return The layer groups in the system model's layout.
   */
  protected Map<Integer, LayerGroup> getLayerGroups() {
    return systemModel.getLayoutModel().getPropertyLayerGroups().getValue();
  }

  /**
   * Returns the layer group for the given layer ID.
   *
   * @param groupId The layer group ID.
   * @return The layer group.
   */
  protected LayerGroup getLayerGroup(int groupId) {
    return getLayerGroups().get(groupId);
  }

  protected void notifyGroupsInitialized() {
    for (LayerGroupChangeListener listener : layerGroupChangeListeners) {
      listener.groupsInitialized();
    }
  }

  protected void notifyGroupsChanged() {
    for (LayerGroupChangeListener listener : layerGroupChangeListeners) {
      listener.groupsChanged();
    }
  }

  protected void notifyGroupAdded() {
    for (LayerGroupChangeListener listener : layerGroupChangeListeners) {
      listener.groupAdded();
    }
  }

  protected void notifyGroupRemoved() {
    for (LayerGroupChangeListener listener : layerGroupChangeListeners) {
      listener.groupRemoved();
    }
  }

  private void restoreComponentsMap() {
    // Prepare an entry in the components map for every registered layer.
    for (LayerWrapper wrapper : getLayerWrappers().values()) {
      components.put(wrapper.getLayer().getId(), new HashSet<>());
    }

    List<DrawnModelComponent> drawnModelComponents = new ArrayList<>();
    drawnModelComponents.addAll(systemModel.getPointModels());
    drawnModelComponents.addAll(systemModel.getPathModels());
    drawnModelComponents.addAll(systemModel.getLocationModels());
    drawnModelComponents.addAll(systemModel.getLinkModels());

    // Add all model components to their respective layer.
    for (DrawnModelComponent modelComponent : drawnModelComponents) {
      addComponent(modelComponent,
                   modelComponent.getPropertyLayerWrapper().getValue().getLayer().getId());
    }

  }

  protected void layerVisibilityChanged(Layer layer, boolean visible) {
    Set<Drawing> drawings = getDrawings();
    SwingUtilities.invokeLater(() -> drawings.forEach(drawing -> drawing.willChange()));
    SwingUtilities.invokeLater(() -> drawings.forEach(drawing -> drawing.changed()));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/AttachmentEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.management;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;

/**
 * Instances of this class represent events emitted by/for attaching comm adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AttachmentEvent
    extends CommAdapterEvent
    implements Serializable {

  /**
   * The vehicle's name a comm adapter has been attached to.
   */
  private final String vehicleName;
  /**
   * The {@link AttachmentInformation} to the actual attachment.
   */
  private final AttachmentInformation updatedAttachmentInformation;

  /**
   * Creates a new instance.
   *
   * @param vehicleName The vehicle's name a comm adapter has been attached to.
   * @param updatedAttachmentInformation The information to the actual attachment.
   */
  public AttachmentEvent(@Nonnull String vehicleName,
                         @Nonnull AttachmentInformation updatedAttachmentInformation) {
    this.vehicleName = requireNonNull(vehicleName, "vehicleName");
    this.updatedAttachmentInformation = requireNonNull(updatedAttachmentInformation,
                                                       "updatedAttachmentInformation");
  }

  /**
   * Returns the vehicle's name a comm adapter has been attached to.
   *
   * @return The vehicle's name a comm adapter has been attached to.
   */
  public String getVehicleName() {
    return vehicleName;
  }

  /**
   * Returns the {@link AttachmentInformation} to the actual attachment.
   *
   * @return The {@link AttachmentInformation} to the actual attachment.
   */
  public AttachmentInformation getUpdatedAttachmentInformation() {
    return updatedAttachmentInformation;
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/KeyValueProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.opentcs.guing.model.ModelComponent;

/**
 * A property containing a key-value pair.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class KeyValueProperty
    extends AbstractComplexProperty {

  /**
   * The key.
   */
  private String fKey;

  /**
   * Creates a new instance.
   *
   * @param model The model component.
   */
  public KeyValueProperty(ModelComponent model) {
    this(model, "", "");
  }

  /**
   * Creates a new instance with a key and value.
   *
   * @param model The model component.
   * @param key The key.
   * @param value The value.
   */
  public KeyValueProperty(ModelComponent model, String key, String value) {
    super(model);
    fKey = key;
    fValue = value;
  }

  @Override
  public Object getComparableValue() {
    return fKey + fValue;
  }

  /**
   * Set the key and the value.
   *
   * @param key The key
   * @param value The value
   */
  public void setKeyAndValue(String key, String value) {
    fKey = key;
    fValue = value;
  }

  /**
   * Returns the key.
   *
   * @return The key of this property.
   */
  public String getKey() {
    return fKey;
  }

  @Override
  public String getValue() {
    return (String) fValue;
  }

  @Override
  public String toString() {
    return fKey + "=" + fValue;
  }

  @Override
  public void copyFrom(Property property) {
    KeyValueProperty keyValueProperty = (KeyValueProperty) property;
    setKeyAndValue(keyValueProperty.getKey(), keyValueProperty.getValue());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/package-info.java<|end_filename|>
/**
 * Components needed for processing information related to comm adapters.
 */
package org.opentcs.drivers.vehicle.management;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/dockable/DockingManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dockable;

import bibliothek.gui.dock.common.SingleCDockable;
import java.beans.PropertyChangeListener;

/**
 * Utility class for working with dockables.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface DockingManager {

  /**
   * PropertyChangeEvent when a floating dockable closes.
   */
  String DOCKABLE_CLOSED = "DOCKABLE_CLOSED";

  /**
   * Adds a PropertyChangeListener.
   *
   * @param listener The new listener.
   */
  void addPropertyChangeListener(PropertyChangeListener listener);

  /**
   * Removes a dockable from the CControl.
   *
   * @param dockable The dockable that shall be removed.
   */
  void removeDockable(SingleCDockable dockable);

  /**
   * Removes a dockable with the given id.
   *
   * @param id The id of the dockable to remove.
   */
  void removeDockable(String id);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/ServiceListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

/**
 * Provides callback methods for instances interested in service updates.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ServiceListener {

  /**
   * Notifies a listener that the service is unavailable, i.e. is not in a usable state.
   */
  void onServiceUnavailable();
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardRouterService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.access.LocalKernel;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;
import org.opentcs.kernel.KernelApplicationConfiguration;
import org.opentcs.kernel.workingset.Model;

/**
 * This class is the standard implementation of the {@link RouterService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardRouterService
    implements RouterService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The kernel.
   */
  private final LocalKernel kernel;
  /**
   * The router.
   */
  private final Router router;
  /**
   * The dispatcher.
   */
  private final Dispatcher dispatcher;
  /**
   * The model facade to the object pool.
   */
  private final Model model;
  /**
   * The kernel application's configuration.
   */
  private final KernelApplicationConfiguration configuration;

  /**
   * Creates a new instance.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param kernel The kernel.
   * @param router The scheduler.
   * @param dispatcher The dispatcher.
   * @param model The model to be used.
   * @param configuration The kernel application's configuration.
   */
  @Inject
  public StandardRouterService(@GlobalSyncObject Object globalSyncObject,
                               LocalKernel kernel,
                               Router router,
                               Dispatcher dispatcher,
                               Model model,
                               KernelApplicationConfiguration configuration) {
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.kernel = requireNonNull(kernel, "kernel");
    this.router = requireNonNull(router, "router");
    this.dispatcher = requireNonNull(dispatcher, "dispatcher");
    this.model = requireNonNull(model, "model");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void updatePathLock(TCSObjectReference<Path> ref, boolean locked)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      model.setPathLocked(ref, locked);
      if (kernel.getState() == Kernel.State.OPERATING
          && configuration.updateRoutingTopologyOnPathLockChange()) {
        updateRoutingTopology();
      }
    }
  }

  @Override
  public void updateRoutingTopology() {
    synchronized (globalSyncObject) {
      router.topologyChanged();
      dispatcher.topologyChanged();
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/PeripheralService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;

/**
 * Provides methods concerning peripheral devices represented by {@link Location}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralService
    extends TCSObjectService {

  /**
   * Attaches the described comm adapter to the referenced location.
   *
   * @param ref A reference to the location.
   * @param description The description for the comm adapter to be attached.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void attachCommAdapter(TCSResourceReference<Location> ref,
                         PeripheralCommAdapterDescription description)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Disables the comm adapter attached to the referenced location.
   *
   * @param ref A reference to the location the comm adapter is attached to.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void disableCommAdapter(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Enables the comm adapter attached to the referenced location.
   *
   * @param ref A reference to the location the comm adapter is attached to.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void enableCommAdapter(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Returns attachment information for the referenced location.
   *
   * @param ref A reference to the location.
   * @return The attachment information.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  PeripheralAttachmentInformation fetchAttachmentInformation(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Returns the process model for the referenced location.
   *
   * @param ref A reference to the location.
   * @return The process model.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  PeripheralProcessModel fetchProcessModel(TCSResourceReference<Location> ref)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Sends a {@link PeripheralAdapterCommand} to the comm adapter attached to the referenced
   * location.
   *
   * @see PeripheralAdapterCommand#execute(PeripheralCommAdapter)
   * @param ref A reference to the location.
   * @param command The adapter command to send.
   * @throws ObjectUnknownException If the referenced location does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void sendCommAdapterCommand(TCSResourceReference<Location> ref, PeripheralAdapterCommand command)
      throws ObjectUnknownException, KernelRuntimeException;
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/PointPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Vector;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.opentcs.guing.components.dialogs.DialogContent;
import org.opentcs.guing.components.dialogs.InputValidationListener;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.PointModel;

/**
 * A UI to select a location or a point as a vehicle destination.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class PointPanel
    extends DialogContent {

  /**
   * Available locations.
   */
  protected List<PointModel> fItems;
  /**
   * List of Listeners to be notified about the validity of user input.
   */
  private final List<InputValidationListener> validationListeners = new LinkedList<>();

  /**
   * Creates new form PointPanel
   *
   * @param items possible destination points
   */
  public PointPanel(List<PointModel> items) {
    initComponents();
    fItems = items;

    Collections.sort(fItems, getComparator());
    List<String> names = new ArrayList<>();

    for (PointModel pointModel : fItems) {
      names.add(pointModel.getName());
    }

    itemsComboBox.setModel(new DefaultComboBoxModel<>(new Vector<>(names)));
    JTextField textField = (JTextField) (itemsComboBox.getEditor().getEditorComponent());
    textField.getDocument().addDocumentListener(new DocumentListener() {
      @Override
      public void insertUpdate(DocumentEvent e) {
        verify();
      }

      @Override
      public void removeUpdate(DocumentEvent e) {
        verify();

      }

      @Override
      public void changedUpdate(DocumentEvent e) {
        verify();

      }

    });
  }

  public void addInputValidationListener(InputValidationListener listener) {
    requireNonNull(listener, "listener");

    this.validationListeners.add(listener);
    verify();
  }

  /**
   * Returns the selected element.
   *
   * @return The selected model component.
   */
  public ModelComponent getSelectedItem() {
    int index = itemsComboBox.getSelectedIndex();

    if (index == -1) {
      return null;
    }
    return fItems.get(index);
  }

  @Override
  public void update() {
  }

  @Override
  public void initFields() {
  }

  protected final Comparator<ModelComponent> getComparator() {
    return new Comparator<ModelComponent>() {

      @Override
      public int compare(ModelComponent item1, ModelComponent item2) {
        String s1 = item1.getName();
        String s2 = item2.getName();
        s1 = s1.toLowerCase();
        s2 = s2.toLowerCase();

        return s1.compareTo(s2);
      }
    };
  }

  private void verify() {
    JTextField textField = (JTextField) (itemsComboBox.getEditor().getEditorComponent());
    String inputText = textField.getText();
    for (PointModel pointModel : fItems) {
      if (pointModel.getName().equals(inputText)) {
        inputValidationSuccessful(true);
        return;
      }
    }
    inputValidationSuccessful(false);
  }

  private void inputValidationSuccessful(boolean success) {
    for (InputValidationListener valListener : validationListeners) {
      valListener.inputValidationSuccessful(success);
    }
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    itemsLabel = new javax.swing.JLabel();
    itemsComboBox = new javax.swing.JComboBox<>();

    setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 10, 5));

    itemsLabel.setFont(itemsLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/operating/dialogs/vehiclePopup"); // NOI18N
    itemsLabel.setText(bundle.getString("pointPanel.label_points.text")); // NOI18N
    add(itemsLabel);

    itemsComboBox.setEditable(true);
    itemsComboBox.setFont(itemsComboBox.getFont());
    add(itemsComboBox);
  }// </editor-fold>//GEN-END:initComponents

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<String> itemsComboBox;
  private javax.swing.JLabel itemsLabel;
  // End of variables declaration//GEN-END:variables
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/scheduling/ReservationPoolTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.scheduling;

import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.aMapWithSize;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.collection.IsMapWithSize.anEmptyMap;
import org.junit.jupiter.api.*;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResource;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class ReservationPoolTest {

  private Scheduler.Client client;
  private ReservationPool reservationPool;

  @BeforeEach
  public void setUp() {
    client = new TestClient();
    reservationPool = new ReservationPool();
  }

  @Test
  public void claimIsEmptyInitially() {
    assertThat(reservationPool.getClaim(client), is(empty()));
  }

  @Test
  public void claimIsEmptyAfterClear() {
    Set<TCSResource<?>> resources = Set.of(new Point("point1"), new Point("point2"));
    List<Set<TCSResource<?>>> claim = List.of(resources);

    reservationPool.setClaim(client, claim);
    reservationPool.clear();

    assertThat(reservationPool.getClaim(client), is(empty()));
  }

  @Test
  public void disallowUnclaimingResourcesNotPreviouslyClaimed() {
    Set<TCSResource<?>> resources = Set.of(new Point("point1"), new Point("point2"));
    List<Set<TCSResource<?>>> claim = List.of(resources);

    reservationPool.setClaim(client, claim);

    assertThatIllegalArgumentException().isThrownBy(
        () -> reservationPool.unclaim(client, Set.of())
    );

    reservationPool.unclaim(client, resources);
  }

  @Test
  public void returnClaimedResources() {
    Set<TCSResource<?>> resources = Set.of(new Point("point1"), new Point("point2"));
    List<Set<TCSResource<?>>> claim = List.of(resources);

    reservationPool.setClaim(client, claim);

    List<Set<TCSResource<?>>> claimedResources = reservationPool.getClaim(client);

    assertThat(claimedResources, hasSize(1));
    assertThat(claimedResources.get(0), hasItems(new Point("point1"), new Point("point2")));
  }

  @Test
  public void confirmNextClaim() {
    Set<TCSResource<?>> resources = Set.of(new Point("point1"), new Point("point2"));
    List<Set<TCSResource<?>>> claim = List.of(resources);

    reservationPool.setClaim(client, claim);

    assertThat(
        reservationPool.isNextInClaim(client, Set.of(new Point("point1"), new Point("point2"))),
        is(true)
    );
  }

  @Test
  public void allocatedResourcesIsEmptyInitially() {
    assertThat(reservationPool.allocatedResources(client), is(empty()));
    assertThat(reservationPool.getAllocations(), is(anEmptyMap()));
  }

  @Test
  public void allocatedResourcesIsEmptyAfterClear() {
    reservationPool.getReservationEntry(new Point("point1")).allocate(client);
    reservationPool.clear();

    assertThat(reservationPool.allocatedResources(client), is(empty()));
  }

  @Test
  public void reflectAllocatedResources() {
    reservationPool.getReservationEntry(new Point("point1")).allocate(client);

    assertThat(reservationPool.allocatedResources(client), hasSize(1));
    assertThat(reservationPool.getAllocations(), is(aMapWithSize(1)));
  }

  @Test
  public void allocatedResourcesIsEmptyAfterFreeAll() {
    reservationPool.getReservationEntry(new Point("point1")).allocate(client);
    reservationPool.freeAll(client);

    assertThat(reservationPool.allocatedResources(client), is(empty()));
    assertThat(reservationPool.getAllocations(), is(anEmptyMap()));
  }

  /**
   * A dummy client for cases in which we need to provide a client but do not have a real one.
   */
  private static class TestClient
      implements Scheduler.Client {

    @Override
    public String getId() {
      return getClass().getName();
    }

    @Override
    public boolean allocationSuccessful(Set<TCSResource<?>> resources) {
      return false;
    }

    @Override
    public void allocationFailed(Set<TCSResource<?>> resources) {
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/candidate/CandidateComparatorByOrderAge.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.candidate;

import java.util.Comparator;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorByAge;

/**
 * Compares {@link AssignmentCandidate}s by age of the order.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorByOrderAge
    implements Comparator<AssignmentCandidate> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "BY_AGE";

  private final Comparator<TransportOrder> delegate = new TransportOrderComparatorByAge();

  /**
   * Compares two candidate by the age of the order.
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param candidate1 The first candidate.
   * @param candidate2 The second candidate.
   * @return the value zero, if the transport order of
   * candidate1 and candidate2 have the same creation time;
   * a value less than zero, if candidate1 is older than candidate2.
   * a value greater than zero otherwise.
   */
  @Override
  public int compare(AssignmentCandidate candidate1, AssignmentCandidate candidate2) {
    return delegate.compare(candidate1.getTransportOrder(), candidate2.getTransportOrder());
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/FigureUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import java.util.HashSet;
import java.util.Set;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.IconToolkit;

/**
 * Represents a Figure component in the TreeView.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class FigureUserObject
    extends AbstractUserObject {

  /**
   * All selected user objects.
   */
  protected Set<UserObject> userObjectItems;

  /**
   * Creates a new instance.
   *
   * @param modelComponent The corresponding data object
   * @param guiManager The gui manager.
   * @param modelManager The model manager
   */
  public FigureUserObject(ModelComponent modelComponent,
                          GuiManager guiManager,
                          ModelManager modelManager) {
    super(modelComponent, guiManager, modelManager);
  }

  @Override // AbstractUserObject
  public String toString() {
    return getModelComponent().getDescription() + " "
        + getModelComponent().getName();
  }

  @Override // AbstractUserObject
  public void doubleClicked() {
    getGuiManager().figureSelected(getModelComponent());
  }

  @Override // AbstractUserObject
  public ImageIcon getIcon() {
    return IconToolkit.instance().createImageIcon("tree/figure.18x18.png");
  }

  @Override // UserObject
  public void rightClicked(JComponent component, int x, int y) {
    userObjectItems = getSelectedUserObjects(((JTree) component));
    super.rightClicked(component, x, y);
  }

  /**
   * Returns the selected user objects in the tree.
   *
   * @param objectTree The tree to find the selected items.
   * @return All selected user objects.
   */
  private Set<UserObject> getSelectedUserObjects(JTree objectTree) {
    Set<UserObject> objects = new HashSet<>();
    TreePath[] selectionPaths = objectTree.getSelectionPaths();

    if (selectionPaths != null) {
      for (TreePath path : selectionPaths) {
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
          if (node.getUserObject() instanceof FigureUserObject) {
            objects.add((UserObject) node.getUserObject());
          }
        }
      }
    }

    return objects;
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/logging/package-info.java<|end_filename|>
/**
 * Utility classes extending basic logging features.
 */
package org.opentcs.util.logging;


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/V004TOMapper.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.opentcs.access.to.model.BlockCreationTO;
import org.opentcs.access.to.model.LocationCreationTO;
import org.opentcs.access.to.model.LocationTypeCreationTO;
import org.opentcs.access.to.model.PathCreationTO;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.model.PointCreationTO;
import org.opentcs.access.to.model.VehicleCreationTO;
import org.opentcs.access.to.model.VisualLayoutCreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.data.model.Block;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.util.Colors;

/**
 * Provides methods for mapping {@link PlantModelCreationTO} to {@link V004PlantModelTO} and
 * vice versa.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V004TOMapper {

  /**
   * The file format version this mapper works with.
   */
  public static final String VERSION_STRING = "0.0.4";

  /**
   * Maps the given model to a {@link PlantModelCreationTO} instance.
   *
   * @param model The model to map.
   * @return The mapped {@link PlantModelCreationTO} instance.
   */
  public PlantModelCreationTO map(V004PlantModelTO model) {
    PlantModelCreationTO result = new PlantModelCreationTO(model.getName())
        .withPoints(toPointCreationTO(model.getPoints()))
        .withVehicles(toVehicleCreationTO(model.getVehicles()))
        .withPaths(toPathCreationTO(model.getPaths()))
        .withLocationTypes(toLocationTypeCreationTO(model.getLocationTypes()))
        .withLocations(toLocationCreationTO(model.getLocations()))
        .withBlocks(toBlockCreationTO(model.getBlocks()))
        .withVisualLayout(toVisualLayoutCreationTO(model.getVisualLayout()))
        .withProperties(convertProperties(model.getProperties()));

    return result;
  }

  /**
   * Maps the given model to a {@link V004PlantModelTO} instance.
   *
   * @param model The model to map.
   * @return The mapped {@link V004PlantModelTO} instance.
   */
  public V004PlantModelTO map(PlantModelCreationTO model) {
    V004PlantModelTO result = new V004PlantModelTO();

    result.setName(model.getName());
    result.setVersion(VERSION_STRING);
    result.getPoints().addAll(toPointTO(model.getPoints(), model.getPaths()));
    result.getVehicles().addAll(toVehicleTO(model.getVehicles()));
    result.getPaths().addAll(toPathTO(model.getPaths()));
    result.getLocationTypes().addAll(toLocationTypeTO(model.getLocationTypes()));
    result.getLocations().addAll(toLocationTO(model.getLocations()));
    result.getBlocks().addAll(toBlockTO(model.getBlocks()));
    result.setVisualLayout(toVisualLayoutTO(model.getVisualLayout()));
    result.getProperties().addAll(convertProperties(model.getProperties()));

    return result;
  }

  //Methods for mapping from PlantModelElementTO to CreationTO start here.
  private List<PointCreationTO> toPointCreationTO(List<PointTO> points) {
    List<PointCreationTO> result = new ArrayList<>();

    for (PointTO point : points) {
      result.add(
          new PointCreationTO(point.getName())
              .withPosition(new Triple(point.getxPosition(),
                                       point.getyPosition(),
                                       point.getzPosition()))
              .withVehicleOrientationAngle(point.getVehicleOrientationAngle().doubleValue())
              .withType(Point.Type.valueOf(point.getType()))
              .withProperties(convertProperties(point.getProperties()))
              .withLayout(new PointCreationTO.Layout(new Couple(point.getPointLayout().getxPosition(),
                                                                point.getPointLayout().getyPosition()),
                                                     new Couple(point.getPointLayout().getxLabelOffset(),
                                                                point.getPointLayout().getyLabelOffset()),
                                                     point.getPointLayout().getLayerId()))
      );
    }

    return result;
  }

  private List<VehicleCreationTO> toVehicleCreationTO(List<VehicleTO> vehicles) {
    List<VehicleCreationTO> result = new ArrayList<>();

    for (VehicleTO vehicle : vehicles) {
      result.add(
          new VehicleCreationTO(vehicle.getName())
              .withLength(vehicle.getLength().intValue())
              .withEnergyLevelCritical(vehicle.getEnergyLevelCritical().intValue())
              .withEnergyLevelGood(vehicle.getEnergyLevelGood().intValue())
              .withEnergyLevelFullyRecharged(vehicle.getEnergyLevelFullyRecharged().intValue())
              .withEnergyLevelSufficientlyRecharged(vehicle.getEnergyLevelSufficientlyRecharged().intValue())
              .withMaxReverseVelocity(vehicle.getMaxReverseVelocity())
              .withMaxVelocity(vehicle.getMaxVelocity())
              .withProperties(convertProperties(vehicle.getProperties()))
              .withLayout(new VehicleCreationTO.Layout(
                  Colors.decodeFromHexRGB(vehicle.getVehicleLayout().getColor())
              ))
      );
    }

    return result;
  }

  private List<PathCreationTO> toPathCreationTO(List<PathTO> paths) {
    List<PathCreationTO> result = new ArrayList<>();

    for (PathTO path : paths) {
      result.add(
          new PathCreationTO(path.getName(),
                             path.getSourcePoint(),
                             path.getDestinationPoint())
              .withLength(path.getLength())
              .withLocked(path.isLocked())
              .withMaxVelocity(path.getMaxVelocity().intValue())
              .withMaxReverseVelocity(path.getMaxReverseVelocity().intValue())
              .withPeripheralOperations(
                  toPeripheralOperationCreationTOs(path.getPeripheralOperations())
              )
              .withProperties(convertProperties(path.getProperties()))
              .withLayout(new PathCreationTO.Layout(
                  Path.Layout.ConnectionType.valueOf(path.getPathLayout().getConnectionType()),
                  path.getPathLayout().getControlPoints().stream()
                      .map(controlPoint -> new Couple(controlPoint.getX(), controlPoint.getY()))
                      .collect(Collectors.toList()),
                  path.getPathLayout().getLayerId()
              ))
      );
    }

    return result;
  }

  private List<PeripheralOperationCreationTO> toPeripheralOperationCreationTOs(
      List<PeripheralOperationTO> tos) {
    return tos.stream()
        .map(
            to -> new PeripheralOperationCreationTO(to.getName(), to.getLocationName())
                .withExecutionTrigger(
                    PeripheralOperation.ExecutionTrigger.valueOf(to.getExecutionTrigger())
                )
                .withCompletionRequired(to.isCompletionRequired())
        )
        .collect(Collectors.toList());
  }

  private List<LocationTypeCreationTO> toLocationTypeCreationTO(
      List<LocationTypeTO> locationTypes) {
    List<LocationTypeCreationTO> result = new ArrayList<>();

    for (LocationTypeTO locationType : locationTypes) {
      result.add(
          new LocationTypeCreationTO(locationType.getName())
              .withAllowedOperations(getOperationNames(locationType.getAllowedOperations()))
              .withAllowedPeripheralOperations(getPeripheralOperationNames(
                  locationType.getAllowedPeripheralOperations())
              )
              .withProperties(convertProperties(locationType.getProperties()))
              .withLayout(new LocationTypeCreationTO.Layout(
                  LocationRepresentation.valueOf(locationType.getLocationTypeLayout().getLocationRepresentation())
              ))
      );
    }

    return result;
  }

  private List<LocationCreationTO> toLocationCreationTO(List<LocationTO> locations) {
    List<LocationCreationTO> result = new ArrayList<>();

    for (LocationTO location : locations) {
      result.add(
          new LocationCreationTO(location.getName(),
                                 location.getType(),
                                 new Triple(location.getxPosition(),
                                            location.getyPosition(),
                                            location.getzPosition()))
              .withLinks(getLinks(location))
              .withLocked(location.isLocked())
              .withProperties(convertProperties(location.getProperties()))
              .withLayout(new LocationCreationTO.Layout(new Couple(location.getLocationLayout().getxPosition(),
                                                                   location.getLocationLayout().getyPosition()),
                                                        new Couple(location.getLocationLayout().getxLabelOffset(),
                                                                   location.getLocationLayout().getyLabelOffset()),
                                                        LocationRepresentation.valueOf(location.getLocationLayout().getLocationRepresentation()),
                                                        location.getLocationLayout().getLayerId()))
      );
    }

    return result;
  }

  private List<BlockCreationTO> toBlockCreationTO(List<BlockTO> blocks) {
    List<BlockCreationTO> result = new ArrayList<>();

    for (BlockTO block : blocks) {
      result.add(
          new BlockCreationTO(block.getName())
              .withType(Block.Type.valueOf(block.getType()))
              .withMemberNames(block.getMembers().stream()
                  .map(member -> member.getName())
                  .collect(Collectors.toSet()))
              .withProperties(convertProperties(block.getProperties()))
              .withLayout(new BlockCreationTO.Layout(
                  Colors.decodeFromHexRGB(block.getBlockLayout().getColor())
              ))
      );
    }

    return result;
  }

  private VisualLayoutCreationTO toVisualLayoutCreationTO(VisualLayoutTO visualLayout) {
    return new VisualLayoutCreationTO(visualLayout.getName())
        .withScaleX(visualLayout.getScaleX())
        .withScaleY(visualLayout.getScaleY())
        .withLayers(convertLayers(visualLayout.getLayers()))
        .withLayerGroups(convertLayerGroups(visualLayout.getLayerGroups()))
        .withProperties(convertProperties(visualLayout.getProperties()));
  }

  private List<Layer> convertLayers(List<VisualLayoutTO.Layer> layers) {
    List<Layer> result = new ArrayList<>();

    for (VisualLayoutTO.Layer layer : layers) {
      result.add(new Layer(layer.getId(),
                           layer.getOrdinal(),
                           layer.isVisible(),
                           layer.getName(),
                           layer.getGroupId()));
    }

    return result;
  }

  private List<LayerGroup> convertLayerGroups(List<VisualLayoutTO.LayerGroup> layerGroups) {
    List<LayerGroup> result = new ArrayList<>();

    for (VisualLayoutTO.LayerGroup layerGroup : layerGroups) {
      result.add(new LayerGroup(layerGroup.getId(),
                                layerGroup.getName(),
                                layerGroup.isVisible()));
    }

    return result;
  }

  private Map<String, String> convertProperties(List<PropertyTO> propsList) {
    Map<String, String> result = new HashMap<>();
    for (PropertyTO property : propsList) {
      String propName
          = isNullOrEmpty(property.getName()) ? "Property unknown" : property.getName();
      String propValue
          = isNullOrEmpty(property.getValue()) ? "Value unknown" : property.getValue();

      result.put(propName, propValue);
    }

    return result;
  }

  private List<String> getOperationNames(List<AllowedOperationTO> ops) {
    List<String> result = new LinkedList<>();
    for (AllowedOperationTO operation : ops) {
      result.add(operation.getName());
    }
    return result;
  }

  private List<String> getPeripheralOperationNames(List<AllowedPeripheralOperationTO> ops) {
    List<String> result = new LinkedList<>();
    for (AllowedPeripheralOperationTO operation : ops) {
      result.add(operation.getName());
    }
    return result;
  }

  private Map<String, Set<String>> getLinks(LocationTO to) {
    Map<String, Set<String>> result = new HashMap<>();
    for (LocationTO.Link linkTO : to.getLinks()) {
      result.put(linkTO.getPoint(),
                 new HashSet<>(getOperationNames(linkTO.getAllowedOperations())));
    }

    return result;
  }

  //Methods for mapping from CreationTO to PlantModelElementTO start here.
  private List<PointTO> toPointTO(List<PointCreationTO> points, List<PathCreationTO> paths) {
    List<PointTO> result = new ArrayList<>();

    for (PointCreationTO point : points) {
      PointTO pointTO = new PointTO();
      pointTO.setName(point.getName());
      pointTO.setxPosition(point.getPosition().getX())
          .setyPosition(point.getPosition().getY())
          .setVehicleOrientationAngle((float) point.getVehicleOrientationAngle())
          .setType(point.getType().name())
          .setOutgoingPaths(getOutgoingPaths(point, paths))
          .setPointLayout(new PointTO.PointLayout()
              .setxPosition(point.getLayout().getPosition().getX())
              .setyPosition(point.getLayout().getPosition().getY())
              .setxLabelOffset(point.getLayout().getLabelOffset().getX())
              .setyLabelOffset(point.getLayout().getLabelOffset().getY())
              .setLayerId(point.getLayout().getLayerId()))
          .setProperties(convertProperties(point.getProperties()));

      result.add(pointTO);
    }

    Collections.sort(result, Comparators.elementsByName());

    return result;
  }

  private List<VehicleTO> toVehicleTO(List<VehicleCreationTO> vehicles) {
    List<VehicleTO> result = new ArrayList<>();

    for (VehicleCreationTO vehicle : vehicles) {
      VehicleTO vehicleTO = new VehicleTO();
      vehicleTO.setName(vehicle.getName());
      vehicleTO.setLength((long) vehicle.getLength())
          .setMaxVelocity(vehicle.getMaxVelocity())
          .setMaxReverseVelocity(vehicle.getMaxReverseVelocity())
          .setEnergyLevelGood((long) vehicle.getEnergyLevelGood())
          .setEnergyLevelCritical((long) vehicle.getEnergyLevelCritical())
          .setEnergyLevelFullyRecharged((long) vehicle.getEnergyLevelFullyRecharged())
          .setEnergyLevelSufficientlyRecharged((long) vehicle.getEnergyLevelSufficientlyRecharged())
          .setVehicleLayout(new VehicleTO.VehicleLayout()
              .setColor(Colors.encodeToHexRGB(vehicle.getLayout().getRouteColor())))
          .setProperties(convertProperties(vehicle.getProperties()));

      result.add(vehicleTO);
    }

    Collections.sort(result, Comparators.elementsByName());

    return result;
  }

  private List<PathTO> toPathTO(List<PathCreationTO> paths) {
    List<PathTO> result = new ArrayList<>();

    for (PathCreationTO path : paths) {
      PathTO pathTO = new PathTO();
      pathTO.setName(path.getName());
      pathTO.setSourcePoint(path.getSrcPointName())
          .setDestinationPoint(path.getDestPointName())
          .setLength(path.getLength())
          .setMaxVelocity((long) path.getMaxVelocity())
          .setMaxReverseVelocity((long) path.getMaxReverseVelocity())
          .setPeripheralOperations(toPeripheralOperationTOs(path.getPeripheralOperations()))
          .setLocked(path.isLocked())
          .setPathLayout(new PathTO.PathLayout()
              .setConnectionType(path.getLayout().getConnectionType().name())
              .setControlPoints(path.getLayout().getControlPoints().stream()
                  .map(controlPoint -> new PathTO.ControlPoint().setX(controlPoint.getX()).setY(controlPoint.getY()))
                  .collect(Collectors.toList()))
              .setLayerId(path.getLayout().getLayerId()))
          .setProperties(convertProperties(path.getProperties()));

      result.add(pathTO);
    }

    Collections.sort(result, Comparators.elementsByName());

    return result;
  }

  private List<PeripheralOperationTO> toPeripheralOperationTOs(
      List<PeripheralOperationCreationTO> tos) {
    return tos.stream()
        .map(
            to -> (PeripheralOperationTO) new PeripheralOperationTO()
                .setLocationName(to.getLocationName())
                .setExecutionTrigger(to.getExecutionTrigger().name())
                .setCompletionRequired(to.isCompletionRequired())
                .setName(to.getOperation())
        )
        .collect(Collectors.toList());
  }

  private List<LocationTypeTO> toLocationTypeTO(
      List<LocationTypeCreationTO> locationTypes) {
    List<LocationTypeTO> result = new ArrayList<>();

    for (LocationTypeCreationTO locationType : locationTypes) {
      LocationTypeTO locationTypeTO = new LocationTypeTO();
      locationTypeTO.setName(locationType.getName());
      locationTypeTO.setAllowedOperations(toAllowedOperationTOs(locationType.getAllowedOperations()))
          .setAllowedPeripheralOperations(toAllowedPeripheralOperationTOs(locationType.getAllowedPeripheralOperations()))
          .setLocationTypeLayout(new LocationTypeTO.LocationTypeLayout()
              .setLocationRepresentation(locationType.getLayout().getLocationRepresentation().name()))
          .setProperties(convertProperties(locationType.getProperties()));

      result.add(locationTypeTO);
    }

    Collections.sort(result, Comparators.elementsByName());

    return result;
  }

  private List<LocationTO> toLocationTO(List<LocationCreationTO> locations) {
    List<LocationTO> result = new ArrayList<>();

    for (LocationCreationTO location : locations) {
      LocationTO locationTO = new LocationTO();
      locationTO.setName(location.getName());
      locationTO.setxPosition(location.getPosition().getX())
          .setyPosition(location.getPosition().getY())
          .setType(location.getTypeName())
          .setLinks(toLocationTOLinks(location.getLinks()))
          .setLocked(location.isLocked())
          .setLocationLayout(new LocationTO.LocationLayout()
              .setxPosition(location.getLayout().getPosition().getX())
              .setyPosition(location.getLayout().getPosition().getY())
              .setxLabelOffset(location.getLayout().getLabelOffset().getX())
              .setyLabelOffset(location.getLayout().getLabelOffset().getY())
              .setLocationRepresentation(location.getLayout().getLocationRepresentation().name())
              .setLayerId(location.getLayout().getLayerId()))
          .setProperties(convertProperties(location.getProperties()));

      result.add(locationTO);
    }

    Collections.sort(result, Comparators.elementsByName());

    return result;
  }

  private List<BlockTO> toBlockTO(List<BlockCreationTO> blocks) {
    List<BlockTO> result = new ArrayList<>();

    for (BlockCreationTO block : blocks) {
      BlockTO blockTO = new BlockTO();
      blockTO.setName(block.getName());
      blockTO.setType(block.getType().name())
          .setMembers(toMemberTOs(block.getMemberNames()))
          .setBlockLayout(new BlockTO.BlockLayout()
              .setColor(Colors.encodeToHexRGB(block.getLayout().getColor())))
          .setProperties(convertProperties(block.getProperties()));

      result.add(blockTO);
    }

    Collections.sort(result, Comparators.elementsByName());

    return result;
  }

  private VisualLayoutTO toVisualLayoutTO(VisualLayoutCreationTO layout) {
    VisualLayoutTO result = new VisualLayoutTO();

    result.setName(layout.getName())
        .setProperties(convertProperties(layout.getProperties()));
    result.setScaleX((float) layout.getScaleX())
        .setScaleY((float) layout.getScaleY())
        .setLayers(toLayerTOs(layout.getLayers()))
        .setLayerGroups(toLayerGroupTOs(layout.getLayerGroups()));

    return result;
  }

  private List<VisualLayoutTO.Layer> toLayerTOs(List<Layer> layers) {
    List<VisualLayoutTO.Layer> result = new ArrayList<>();

    for (Layer layer : layers) {
      result.add(new VisualLayoutTO.Layer()
          .setId(layer.getId())
          .setOrdinal(layer.getOrdinal())
          .setVisible(layer.isVisible())
          .setName(layer.getName())
          .setGroupId(layer.getGroupId()));
    }

    return result;
  }

  private List<VisualLayoutTO.LayerGroup> toLayerGroupTOs(List<LayerGroup> layerGroups) {
    List<VisualLayoutTO.LayerGroup> result = new ArrayList<>();

    for (LayerGroup layerGroup : layerGroups) {
      result.add(new VisualLayoutTO.LayerGroup()
          .setId(layerGroup.getId())
          .setName(layerGroup.getName())
          .setVisible(layerGroup.isVisible()));
    }

    return result;
  }

  private List<PointTO.OutgoingPath> getOutgoingPaths(PointCreationTO point,
                                                      List<PathCreationTO> paths) {
    List<PointTO.OutgoingPath> result = new ArrayList<>();

    for (PathCreationTO path : paths) {
      if (Objects.equals(path.getSrcPointName(), point.getName())) {
        result.add(new PointTO.OutgoingPath().setName(path.getName()));
      }
    }

    Collections.sort(result, Comparators.outgoingPathsByName());

    return result;
  }

  private List<AllowedOperationTO> toAllowedOperationTOs(Collection<String> allowedOperations) {
    return allowedOperations.stream()
        .sorted()
        .map(allowedOperation -> (AllowedOperationTO) new AllowedOperationTO().setName(allowedOperation))
        .collect(Collectors.toList());
  }

  private List<AllowedPeripheralOperationTO> toAllowedPeripheralOperationTOs(
      Collection<String> allowedOperations) {
    return allowedOperations.stream()
        .sorted()
        .map(allowedOperation -> (AllowedPeripheralOperationTO) new AllowedPeripheralOperationTO().setName(allowedOperation))
        .collect(Collectors.toList());
  }

  private List<LocationTO.Link> toLocationTOLinks(Map<String, Set<String>> links) {
    List<LocationTO.Link> result = new ArrayList<>();

    links.forEach((key, value) -> {
      result.add(
          new LocationTO.Link()
              .setPoint(key)
              .setAllowedOperations(toAllowedOperationTOs(value))
      );
    });

    Collections.sort(result, Comparators.linksByPointName());

    return result;
  }

  private List<MemberTO> toMemberTOs(Collection<String> members) {
    return members.stream()
        .map(member -> (MemberTO) new MemberTO().setName(member))
        .sorted(Comparators.elementsByName())
        .collect(Collectors.toList());
  }

  private List<PropertyTO> convertProperties(Map<String, String> properties) {
    List<PropertyTO> result = new ArrayList<>();

    properties.forEach((key, value) -> {
      result.add(new PropertyTO().setName(key).setValue(value));
    });

    Collections.sort(result, Comparators.propertiesByName());

    return result;
  }

  private boolean isNullOrEmpty(String s) {
    return s == null || s.isEmpty();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/DispatcherService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.data.order.TransportOrder.State;

/**
 * Provides methods concerning the {@link Dispatcher}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface DispatcherService {

  /**
   * Explicitly trigger the dispatching process.
   *
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void dispatch()
      throws KernelRuntimeException;

  /**
   * Withdraw any order that a vehicle might be processing.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param immediateAbort If {@code false}, this method once will initiate the withdrawal, leaving
   * the transport order assigned to the vehicle until it has finished the movements that it has
   * already been ordered to execute. The transport order's state will change to
   * {@link State#WITHDRAWN}. If {@code true}, the dispatcher will withdraw the order from the
   * vehicle without further waiting.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void withdrawByVehicle(TCSObjectReference<Vehicle> ref, boolean immediateAbort)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Withdraw the referenced order.
   *
   * @param ref A reference to the transport order to be withdrawn.
   * @param immediateAbort If {@code false}, this method once will initiate the withdrawal, leaving
   * the transport order assigned to the vehicle until it has finished the movements that it has
   * already been ordered to execute. The transport order's state will change to
   * {@link State#WITHDRAWN}. If {@code true}, the dispatcher will withdraw the order from the
   * vehicle without further waiting.
   * @throws ObjectUnknownException If the referenced transport order does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void withdrawByTransportOrder(TCSObjectReference<TransportOrder> ref, boolean immediateAbort)
      throws ObjectUnknownException, KernelRuntimeException;
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/VehicleUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.IconToolkit;

/**
 * Represents a vehicle object in the TreeView.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class VehicleUserObject
    extends AbstractUserObject {

  /**
   * All selected vehicles.
   */
  protected Set<VehicleModel> selectedVehicles;

  /**
   * Creates a new instance.
   *
   * @param model The corresponding vehicle object.
   * @param guiManager The gui manager.
   * @param modelManager Provides the current system model.
   */
  @Inject
  public VehicleUserObject(@Assisted VehicleModel model,
                           GuiManager guiManager,
                           ModelManager modelManager) {
    super(model, guiManager, modelManager);
  }

  @Override
  public VehicleModel getModelComponent() {
    return (VehicleModel) super.getModelComponent();
  }

  @Override  // AbstractUserObject
  public void doubleClicked() {
    getGuiManager().figureSelected(getModelComponent());
  }

  @Override // UserObject
  public void rightClicked(JComponent component, int x, int y) {
    selectedVehicles = getSelectedVehicles(((JTree) component));
    super.rightClicked(component, x, y);
  }

  @Override  // AbstractUserObject
  public ImageIcon getIcon() {
    return IconToolkit.instance().createImageIcon("tree/vehicle.18x18.png");
  }

  /**
   * Returns the selected vehicle models in the tree.
   *
   * @param objectTree The tree to find the selected items.
   * @return All selected vehicle models.
   */
  private Set<VehicleModel> getSelectedVehicles(JTree objectTree) {
    Set<VehicleModel> objects = new HashSet<>();
    TreePath[] selectionPaths = objectTree.getSelectionPaths();

    if (selectionPaths != null) {
      for (TreePath path : selectionPaths) {
        if (path != null) {
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
          //vehicles can only be selected with other vehicles
          if (node.getUserObject() instanceof VehicleUserObject) {
            objects.add((VehicleModel) ((UserObject) node.getUserObject()).getModelComponent());
          }
        }
      }
    }

    return objects;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/SchedulerAllocationState.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opentcs.data.model.TCSResource;

/**
 * Represents the current state of resource allocations.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SchedulerAllocationState
    implements Serializable {

  /**
   * The current state of allocations.
   */
  private final Map<String, Set<TCSResource<?>>> allocationStates;

  /**
   * Creates a new instance.
   *
   * @param allocationStates The current state of allocations.
   */
  public SchedulerAllocationState(@Nonnull Map<String, Set<TCSResource<?>>> allocationStates) {
    this.allocationStates = Collections.unmodifiableMap(requireNonNull(allocationStates,
                                                                       "allocationStates"));
  }

  /**
   * Returns the current state of allocations.
   *
   * @return The current state of allocations.
   */
  public Map<String, Set<TCSResource<?>>> getAllocationStates() {
    return allocationStates;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/course/Origin.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.course;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.EventObject;
import java.util.HashSet;
import java.util.Set;
import org.opentcs.guing.components.drawing.figures.OriginFigure;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The origin of the coordinate system. Represents the current scale, coordinate system and
 * position of the origin on the screen.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public final class Origin {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(Origin.class);
  /**
   * Scale (in mm per pixel) of the layout.
   */
  public static final double DEFAULT_SCALE = 50.0;
  /**
   * Amount of mm to equal one pixel on screen in horizontal direction.
   */
  private double fScaleX = DEFAULT_SCALE;
  /**
   * Amount of mm to equal one pixel on screen in horizontal direction.
   */
  private double fScaleY = DEFAULT_SCALE;
  /**
   * Current position in pixels.
   */
  private Point fPosition;
  /**
   * The coordinate system.
   */
  private CoordinateSystem fCoordinateSystem;
  /**
   * List of {@link OriginChangeListener}.
   */
  private final Set<OriginChangeListener> fListeners = new HashSet<>();
  /**
   * Graphical figure to represent the origin.
   */
  private final OriginFigure fFigure = new OriginFigure();

  /**
   * Creates a new instance of Origin
   */
  public Origin() {
    setCoordinateSystem(new NormalCoordinateSystem());
    fFigure.setModel(this);
  }

  /**
   * Set the scale in millimeter per pixel.
   */
  public void setScale(double scaleX, double scaleY) {
    if (fScaleX == scaleX && fScaleY == scaleY) {
      return;
    }
    fScaleX = scaleX;
    fScaleY = scaleY;
    notifyScaleChanged();
  }

  /**
   * Return the millimeter per pixel in horizontal direction.
   *
   * @return the millimeter per pixel in horizontal direction.
   */
  public double getScaleX() {
    return fScaleX;
  }

  /**
   * Return the millimeter per pixel in vertical direction.
   *
   * @return the millimeter per pixel in vertical direction.
   */
  public double getScaleY() {
    return fScaleY;
  }

  /**
   * Set the coordinate system.
   */
  public void setCoordinateSystem(CoordinateSystem coordinateSystem) {
    fCoordinateSystem = coordinateSystem;
    notifyLocationChanged();
  }

  /**
   * Set the position of the origin.
   *
   * @param position the position of the origin.
   */
  public void setPosition(Point position) {
    fPosition = position;
  }

  /**
   * Return the current position of the origin.
   *
   * @return the current position of the origin.
   */
  public Point getPosition() {
    return fPosition;
  }

  /**
   * Translates the real coordinate into pixel coordinates.
   *
   * @param xReal The real x position.
   * @param yReal The real y position.
   * @return A point with the pixel position.
   */
  public Point calculatePixelPosition(LengthProperty xReal, LengthProperty yReal) {
    Point2D pixelExact = calculatePixelPositionExactly(xReal, yReal);

    return new Point((int) pixelExact.getX(), (int) pixelExact.getY());
  }

  /**
   * Translates the real coordinate into pixel coordinates with double precision.
   *
   * @param xReal The real x position.
   * @param yReal The real y position.
   * @return A point with the pixel position with double precision.
   */
  public Point2D calculatePixelPositionExactly(LengthProperty xReal, LengthProperty yReal) {
    Point2D realPosition = new Point2D.Double(
        xReal.getValueByUnit(LengthProperty.Unit.MM),
        yReal.getValueByUnit(LengthProperty.Unit.MM));

    Point2D pixelPosition = fCoordinateSystem.toPixel(fPosition, realPosition, fScaleX, fScaleY);

    return pixelPosition;
  }

  /**
   * Translates the real coordinate into pixel coordinates with double precision from
   * string properties.
   *
   * @param xReal The real x position.
   * @param yReal The real y position.
   * @return A point with the pixel position with double precision.
   */
  public Point2D calculatePixelPositionExactly(StringProperty xReal, StringProperty yReal) {
    try {
      double xPos = Double.parseDouble(xReal.getText());
      double yPos = Double.parseDouble(yReal.getText());
      Point2D realPosition = new Point2D.Double(xPos, yPos);
      Point2D pixelPosition = fCoordinateSystem.toPixel(fPosition, realPosition, fScaleX, fScaleY);

      return pixelPosition;
    }
    catch (NumberFormatException e) {
      LOG.info("Couldn't parse layout coordinates", e);
      return new Point2D.Double();
    }
  }

  /**
   * Translates a pixel position into a real position and write to the length properties.
   *
   *
   * @param pixelPosition The pixel position to convert.
   * @param xReal The length property to write the x position to.
   * @param yReal The length property to write the y position to.
   * @return A point with the pixel position with double precision.
   */
  public Point2D calculateRealPosition(Point pixelPosition, LengthProperty xReal,
                                       LengthProperty yReal) {
    Point2D realPosition = fCoordinateSystem.toReal(fPosition, pixelPosition, fScaleX, fScaleY);

    LengthProperty.Unit unitX = xReal.getUnit();
    LengthProperty.Unit unitY = yReal.getUnit();

    xReal.setValueAndUnit((int) realPosition.getX(), LengthProperty.Unit.MM);
    yReal.setValueAndUnit((int) realPosition.getY(), LengthProperty.Unit.MM);
    xReal.convertTo(unitX);
    yReal.convertTo(unitY);

    return realPosition;
  }

  /**
   * Translates a pixel position onto a real position.
   *
   * @param pixelPosition The pixel position to convert.
   * @return A point with the pixel position with double precision.
   */
  public Point2D calculateRealPosition(Point pixelPosition) {
    Point2D realPosition = fCoordinateSystem.toReal(fPosition, pixelPosition, fScaleX, fScaleY);

    return realPosition;
  }

  /**
   * Add an origin change listener.
   *
   * @param l The origin change listener to add.
   */
  public void addListener(OriginChangeListener l) {
    fListeners.add(l);
  }

  /**
   * Remove an origin change listener.
   *
   * @param l The origin change listener to remove.
   */
  public void removeListener(OriginChangeListener l) {
    fListeners.remove(l);
  }

  /**
   *
   * Tests whether a specific origin change listener is registerd.
   *
   * @param l The origin change listener to test for.
   * @return <code> true </code>, if the listener is registerd.
   */
  public boolean containsListener(OriginChangeListener l) {
    return fListeners.contains(l);
  }

  /**
   * Notifies all registered listeners that the position of the origin has changed.
   */
  public void notifyLocationChanged() {
    for (OriginChangeListener l : fListeners) {
      l.originLocationChanged(new EventObject(this));
    }
  }

  /**
   * Notifies all registered listeners that the scale has changed.
   */
  public void notifyScaleChanged() {
    for (OriginChangeListener l : fListeners) {
      l.originScaleChanged(new EventObject(this));
    }
  }

  /**
   * Return the graphical representation of the origin.
   *
   * @return The graphical representation of the origin.
   */
  public OriginFigure getFigure() {
    return fFigure;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/routing/EdgeEvaluator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.routing;

import javax.annotation.Nonnull;
import org.opentcs.data.model.Vehicle;

/**
 * Computes the weight of edges in the routing graph.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface EdgeEvaluator {

  /**
   * Computes the weight of an edge in the routing graph.
   *
   * @param edge The edge.
   * @param vehicle The vehicle for which to compute the edge's weight.
   * @return The computed weight of the given edge.
   * A value of {@code Double.POSITIVE_INFINITY} indicates that the edge is to be excluded from
   * routing.
   * Note that negative weights might not be handled well by the respective routing algorithm used.
   */
  double computeWeight(@Nonnull Edge edge, @Nonnull Vehicle vehicle);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/StartupProgressStatus.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import java.util.ResourceBundle;
import org.opentcs.guing.util.I18nPlantOverview;

/**
 * Progress status for the process of starting the application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public enum StartupProgressStatus
    implements ProgressStatus {

  START_PLANT_OVERVIEW(0, "startupProgressStatus.description.startPlantOverview"),
  SHOW_PLANT_OVERVIEW(5, "startupProgressStatus.description.showPlantOverview"),
  INITIALIZED(10, "startupProgressStatus.description.initialized"),
  INITIALIZE_MODEL(15, "startupProgressStatus.description.initializeModel");

  private final int percentage;

  private final String description;

  private StartupProgressStatus(int percentage, String description) {
    this.percentage = percentage;
    this.description = ResourceBundle.getBundle(I18nPlantOverview.MISC_PATH).getString(description);
  }

  @Override
  public int getPercentage() {
    return percentage;
  }

  @Override
  public String getStatusDescription() {
    return description;
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/orders/IsFreelyDispatchableToAnyVehicle.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.orders;

import static java.util.Objects.requireNonNull;
import java.util.function.Predicate;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.OrderReservationPool;
import org.opentcs.strategies.basic.dispatching.selection.TransportOrderSelectionFilter;

/**
 * Filters transport orders that are dispatchable and available to <em>any</em> vehicle.
 *
 * <p>
 * Note: This filter is not a {@link TransportOrderSelectionFilter} by intention, since it is not
 * intended to be used in contexts where {@link ObjectHistory} entries are created.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class IsFreelyDispatchableToAnyVehicle
    implements Predicate<TransportOrder> {

  /**
   * The order service.
   */
  private final TCSObjectService objectService;
  /**
   * Stores reservations of orders for vehicles.
   */
  private final OrderReservationPool orderReservationPool;

  /**
   * Creates a new isntance.
   *
   * @param objectService The order service.
   * @param orderReservationPool Stores reservations of orders for vehicles.
   */
  @Inject
  public IsFreelyDispatchableToAnyVehicle(TCSObjectService objectService,
                                          OrderReservationPool orderReservationPool) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.orderReservationPool = requireNonNull(orderReservationPool, "orderReservationPool");
  }

  @Override
  public boolean test(TransportOrder order) {
    // We only want to check dispatchable transport orders.
    // Filter out transport orders that are intended for other vehicles.
    // Also filter out all transport orders with reservations. We assume that a check for reserved
    // orders has been performed already, and if any had been found, we wouldn't have been called.
    return order.hasState(TransportOrder.State.DISPATCHABLE)
        && !partOfAnyVehiclesSequence(order)
        && !orderReservationPool.isReserved(order.getReference());
  }

  private boolean partOfAnyVehiclesSequence(TransportOrder order) {
    if (order.getWrappingSequence() == null) {
      return false;
    }
    OrderSequence seq = objectService.fetchObject(OrderSequence.class,
                                                  order.getWrappingSequence());
    return seq != null && seq.getProcessingVehicle() != null;
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/FigureDecorationDetails.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.Set;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * Provides methods to configure the data that is used to decorate a model component's figure.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface FigureDecorationDetails {

  /**
   * Adds a vehicle model.
   *
   * @param model The vehicle model.
   */
  void addVehicleModel(VehicleModel model);

  /**
   * Removes a vehicle model.
   *
   * @param model The vehicle model.
   */
  void removeVehicleModel(VehicleModel model);

  /**
   * Returns a set of vehicle models for which a model component's figure is to be decorated to
   * indicate that the model component is part of the route of the respective vehicles.
   *
   * @return A set of vehicle models.
   */
  Set<VehicleModel> getVehicleModels();

  /**
   * Adds a block model.
   *
   * @param model The block model.
   */
  void addBlockModel(BlockModel model);

  /**
   * Removes a block model.
   *
   * @param model The block model.
   */
  void removeBlockModel(BlockModel model);

  /**
   * Returns a set of block models for which a model component's figure is to be decorated to
   * indicate that the model component is part of the respective block.
   *
   * @return A set of block models.
   */
  Set<BlockModel> getBlockModels();
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/transport/OrderTypeSuggestionsPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.TreeSet;
import javax.inject.Inject;
import org.opentcs.components.plantoverview.OrderTypeSuggestions;

/**
 * A collection of all transport order types suggested.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderTypeSuggestionsPool
    implements OrderTypeSuggestions {

  /**
   * The transport order type suggestions.
   */
  private final Set<String> typeSuggestions = new TreeSet<>();

  @Inject
  public OrderTypeSuggestionsPool(Set<OrderTypeSuggestions> typeSuggestions) {
    requireNonNull(typeSuggestions, "typeSuggestions");

    for (OrderTypeSuggestions typeSuggestion : typeSuggestions) {
      this.typeSuggestions.addAll(typeSuggestion.getTypeSuggestions());
    }
  }

  @Override
  public Set<String> getTypeSuggestions() {
    return typeSuggestions;
  }

  /**
   * Adds an additional type to the pool.
   *
   * @param typeSuggestion The type to add.
   */
  public void addTypeSuggestion(String typeSuggestion) {
    typeSuggestions.add(typeSuggestion);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/ViewManagerOperating.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.intern.DefaultCommonDockable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.TreeMap;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.guing.components.dockable.CStackDockStation;
import org.opentcs.guing.components.dockable.DockableTitleComparator;
import org.opentcs.guing.components.dockable.DockingManagerOperating;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.peripherals.jobs.PeripheralJobsContainerPanel;
import org.opentcs.guing.transport.orders.TransportOrdersContainerPanel;
import org.opentcs.guing.transport.sequences.OrderSequencesContainerPanel;
import org.opentcs.util.event.EventSource;

/**
 * Manages the mapping of dockables to drawing views, transport order views and
 * order sequence views.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewManagerOperating
    extends AbstractViewManager {

  /**
   * Manages the application's docking frames.
   */
  private final DockingManagerOperating dockingManager;
  /**
   * Where we register event listeners.
   */
  private final EventSource eventSource;
  /**
   * Map for transport order dockable -> transport order container panel.
   */
  private final Map<DefaultSingleCDockable, TransportOrdersContainerPanel> transportOrderViews;
  /**
   * Map for order sequences dockable -> order sequences container panel.
   */
  private final Map<DefaultSingleCDockable, OrderSequencesContainerPanel> orderSequenceViews;
  /**
   * Map for peripheral job dockable -> peripheral job container panel.
   */
  private final Map<DefaultSingleCDockable, PeripheralJobsContainerPanel> peripheralJobViews;

  /**
   * Creates a new instance.
   *
   * @param dockingManager Manages the application's docking frames.
   * @param eventSource Where this instance registers event listeners.
   */
  @Inject
  public ViewManagerOperating(DockingManagerOperating dockingManager,
                              @ApplicationEventBus EventSource eventSource) {
    super(eventSource);
    this.dockingManager = requireNonNull(dockingManager, "dockingManager");
    this.eventSource = requireNonNull(eventSource, "eventSource");
    transportOrderViews = new TreeMap<>(new DockableTitleComparator());
    orderSequenceViews = new TreeMap<>(new DockableTitleComparator());
    peripheralJobViews = new TreeMap<>(new DockableTitleComparator());
  }

  public void init() {
    setPlantOverviewStateOperating();
  }

  /**
   * Resets all components.
   */
  public void reset() {
    super.reset();
    transportOrderViews.clear();
    orderSequenceViews.clear();
    peripheralJobViews.clear();
  }

  public Map<DefaultSingleCDockable, TransportOrdersContainerPanel> getTransportOrderMap() {
    return transportOrderViews;
  }

  public Map<DefaultSingleCDockable, OrderSequencesContainerPanel> getOrderSequenceMap() {
    return orderSequenceViews;
  }

  public Map<DefaultSingleCDockable, PeripheralJobsContainerPanel> getPeripheralJobMap() {
    return peripheralJobViews;
  }

  /**
   * Returns all drawing views (excluding the modelling view)
   *
   * @return List with all known <code>OpenTCSDrawingViews</code>, but not
   * the modelling view.
   */
  public List<OpenTCSDrawingView> getOperatingDrawingViews() {
    return getDrawingViewMap().entrySet().stream()
        .map(entry -> entry.getValue().getDrawingView())
        .collect(Collectors.toList());
  }

  public int getNextTransportOrderViewIndex() {
    return nextAvailableIndex(transportOrderViews.keySet());
  }

  public int getNextOrderSequenceViewIndex() {
    return nextAvailableIndex(orderSequenceViews.keySet());
  }

  public int getNextPeripheralJobViewIndex() {
    return nextAvailableIndex(peripheralJobViews.keySet());
  }

  public DefaultSingleCDockable getLastTransportOrderView() {
    int biggestIndex = getNextTransportOrderViewIndex();
    DefaultSingleCDockable lastTOView = null;
    Iterator<DefaultSingleCDockable> tranportOrderViewIterator
        = transportOrderViews.keySet().iterator();
    for (int i = 0; i < biggestIndex; i++) {
      if (tranportOrderViewIterator.hasNext()) {
        lastTOView = tranportOrderViewIterator.next();
      }
    }

    return lastTOView;
  }

  public DefaultSingleCDockable getLastOrderSequenceView() {
    int biggestIndex = getNextOrderSequenceViewIndex();
    DefaultSingleCDockable lastOSView = null;
    Iterator<DefaultSingleCDockable> orderSequencesViewIterator
        = orderSequenceViews.keySet().iterator();
    for (int i = 0; i < biggestIndex; i++) {
      if (orderSequencesViewIterator.hasNext()) {
        lastOSView = orderSequencesViewIterator.next();
      }
    }

    return lastOSView;
  }

  public DefaultSingleCDockable getLastPeripheralJobView() {
    int biggestIndex = getNextPeripheralJobViewIndex();
    DefaultSingleCDockable lastView = null;
    Iterator<DefaultSingleCDockable> peripheralJobViewIterator
        = peripheralJobViews.keySet().iterator();
    for (int i = 0; i < biggestIndex; i++) {
      if (peripheralJobViewIterator.hasNext()) {
        lastView = peripheralJobViewIterator.next();
      }
    }

    return lastView;
  }

  /**
   * Puts a <code>TransportOrdersContainerPanel</code> with a key dockable
   * into the transport order view map.
   *
   * @param dockable The dockable the panel is wrapped into. Used as the key.
   * @param panel The panel.
   */
  public void addTransportOrderView(DefaultSingleCDockable dockable,
                                    TransportOrdersContainerPanel panel) {
    requireNonNull(dockable, "dockable");
    requireNonNull(panel, "panel");

    transportOrderViews.put(dockable, panel);
  }

  /**
   * Puts a <code>OrderSequencesContainerPanel</code> with a key dockable
   * into the order sequence view map.
   *
   * @param dockable The dockable the panel is wrapped into. Used as the key.
   * @param panel The panel.
   */
  public void addOrderSequenceView(DefaultSingleCDockable dockable,
                                   OrderSequencesContainerPanel panel) {
    requireNonNull(dockable, "dockable");
    requireNonNull(panel, "panel");

    orderSequenceViews.put(dockable, panel);
  }

  /**
   * Puts a <code>OrderSequencesContainerPanel</code> with a key dockable
   * into the order sequence view map.
   *
   * @param dockable The dockable the panel is wrapped into. Used as the key.
   * @param panel The panel.
   */
  public void addPeripheralJobView(DefaultSingleCDockable dockable,
                                   PeripheralJobsContainerPanel panel) {
    requireNonNull(dockable, "dockable");
    requireNonNull(panel, "panel");

    peripheralJobViews.put(dockable, panel);
  }

  /**
   * Forgets the given dockable.
   *
   * @param dockable The dockable.
   */
  @Override
  public void removeDockable(DefaultSingleCDockable dockable) {
    super.removeDockable(dockable);

    transportOrderViews.remove(dockable);
    orderSequenceViews.remove(dockable);
    peripheralJobViews.remove(dockable);
  }

  /**
   * Evaluates which dockable should be the front dockable.
   *
   * @return The dockable that should be the front dockable. <code>null</code>
   * if no dockables exist.
   */
  @Override
  public DefaultCommonDockable evaluateFrontDockable() {
    if (!getDrawingViewMap().isEmpty()) {
      return getDrawingViewMap().keySet().iterator().next().intern();
    }
    if (!transportOrderViews.isEmpty()) {
      return transportOrderViews.keySet().iterator().next().intern();
    }
    if (!orderSequenceViews.isEmpty()) {
      return orderSequenceViews.keySet().iterator().next().intern();
    }
    if (!peripheralJobViews.isEmpty()) {
      return peripheralJobViews.keySet().iterator().next().intern();
    }
    return null;
  }

  /**
   * Sets visibility states of all dockables to operating.
   */
  private void setPlantOverviewStateOperating() {
    CStackDockStation station
        = dockingManager.getTabPane(DockingManagerOperating.COURSE_TAB_PANE_ID).getStation();
    Dockable frontDock = station.getFrontDockable();
    int i = 0;
    for (DefaultSingleCDockable dock : new ArrayList<>(getDrawingViewMap().keySet())) {
      // Restore to default
      dock.setCloseable(true);
      dockingManager.showDockable(station, dock, i);
      i++;
    }
    i = getDrawingViewMap().size();
    for (DefaultSingleCDockable dock : new ArrayList<>(getDrawingViewMap().keySet())) {
      // OpenTCSDrawingViews can be undocked when switching states, so
      // we make sure they aren't counted as docked
      if (dockingManager.isDockableDocked(station, dock)) {
        i--;
      }
    }

    int dockedDrawingViews = i;

    for (DefaultSingleCDockable dock : new ArrayList<>(transportOrderViews.keySet())) {
      dockingManager.showDockable(station, dock, i);
      i++;
    }

    i = dockedDrawingViews + transportOrderViews.size();

    for (DefaultSingleCDockable dock : new ArrayList<>(orderSequenceViews.keySet())) {
      dockingManager.showDockable(station, dock, i);
      i++;
    }

    for (DefaultSingleCDockable dock : new ArrayList<>(peripheralJobViews.keySet())) {
      dockingManager.showDockable(station, dock, i);
      i++;
    }

    if (frontDock != null && frontDock.isDockableShowing()) {
      station.setFrontDockable(frontDock);
    }
    else {
      station.setFrontDockable(station.getDockable(0));
    }
    dockingManager.setDockableVisibility(DockingManagerOperating.VEHICLES_DOCKABLE_ID, true);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/AssignSequenceSuccessorsPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import static java.util.Objects.requireNonNull;
import java.util.Optional;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;

/**
 * Assigns vehicles to the next transport orders in their respective order sequences, if any.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignSequenceSuccessorsPhase
    implements Phase {

  /**
   * The object service
   */
  private final TCSObjectService objectService;
  /**
   * The Router instance calculating route costs.
   */
  private final Router router;
  /**
   * A collection of predicates for filtering assignment candidates.
   */
  private final CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter;

  private final TransportOrderUtil transportOrderUtil;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public AssignSequenceSuccessorsPhase(
      TCSObjectService objectService,
      Router router,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      TransportOrderUtil transportOrderUtil) {
    this.router = requireNonNull(router, "router");
    this.objectService = requireNonNull(objectService, "objectService");
    this.assignmentCandidateSelectionFilter = requireNonNull(assignmentCandidateSelectionFilter,
                                                             "assignmentCandidateSelectionFilter");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    for (Vehicle vehicle : objectService.fetchObjects(Vehicle.class,
                                                      this::readyForNextInSequence)) {
      tryAssignNextOrderInSequence(vehicle);
    }
  }

  private void tryAssignNextOrderInSequence(Vehicle vehicle) {
    nextOrderInCurrentSequence(vehicle)
        .map(order -> computeCandidate(vehicle, order))
        .filter(candidate -> assignmentCandidateSelectionFilter.apply(candidate).isEmpty())
        .ifPresent(candidate -> transportOrderUtil.assignTransportOrder(vehicle,
                                                                        candidate.getTransportOrder(),
                                                                        candidate.getDriveOrders()));
  }

  private AssignmentCandidate computeCandidate(Vehicle vehicle, TransportOrder order) {
    return router.getRoute(vehicle,
                           objectService.fetchObject(Point.class, vehicle.getCurrentPosition()),
                           order)
        .map(driveOrders -> new AssignmentCandidate(vehicle, order, driveOrders))
        .orElse(null);
  }

  private Optional<TransportOrder> nextOrderInCurrentSequence(Vehicle vehicle) {
    OrderSequence seq = objectService.fetchObject(OrderSequence.class, vehicle.getOrderSequence());

    // If the order sequence's next order is not available, yet, the vehicle should wait for it.
    if (seq.getNextUnfinishedOrder() == null) {
      return Optional.empty();
    }

    // Return the next order to be processed for the sequence.
    return Optional.of(objectService.fetchObject(TransportOrder.class,
                                                 seq.getNextUnfinishedOrder()));
  }

  private boolean readyForNextInSequence(Vehicle vehicle) {
    return vehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_UTILIZED
        && vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && vehicle.hasState(Vehicle.State.IDLE)
        && vehicle.getCurrentPosition() != null
        && vehicle.getOrderSequence() != null;
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/decoration/PointOutlineHandle.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures.decoration;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RadialGradientPaint;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.jhotdraw.draw.AttributeKeys;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.handle.BoundsOutlineHandle;
import org.opentcs.guing.components.drawing.figures.PointFigure;

/**
 *
 * 
 * @author <NAME> (Fraunhofer IML)
 */
public class PointOutlineHandle
    extends BoundsOutlineHandle {

  public PointOutlineHandle(Figure owner) {
    super(owner);
  }

  @Override
  public void draw(Graphics2D g) {
    PointFigure pf = (PointFigure) getOwner();
    Shape bounds = pf.getShape();

    if (getOwner().get(AttributeKeys.TRANSFORM) != null) {
      bounds = getOwner().get(AttributeKeys.TRANSFORM).createTransformedShape(bounds);
    }

    if (view != null) {
      bounds = view.getDrawingToViewTransform().createTransformedShape(bounds);
      Rectangle2D bounds2D = bounds.getBounds2D();
      float centerX = (float) bounds2D.getCenterX();
      float centerY = (float) bounds2D.getCenterY();
      Point2D center = new Point2D.Float(centerX, centerY);
      float radius = 10.0f;
      float[] dist = {0.1f, 0.9f};
      Color[] colors = {Color.CYAN, Color.BLUE};

      RadialGradientPaint radialGradientPaint = new RadialGradientPaint(center, radius, dist, colors);
      Paint oldPaint = g.getPaint();
      g.setPaint(radialGradientPaint);

      g.fill(bounds);
      g.setPaint(oldPaint);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/I18nPlantOverview.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

/**
 * Defines constants regarding internationalization.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface I18nPlantOverview {
  
  /**
   * Path to the resources related the menu bar.
   */
  String MENU_PATH = "i18n.org.opentcs.plantoverview.mainMenu";
  /**
   * Path to miscellaneous resources
   */
  String MISC_PATH = "i18n.org.opentcs.plantoverview.miscellaneous";
  /**
   * Path to the resources related to the system.
   */
  String SYSTEM_PATH = "i18n.org.opentcs.plantoverview.system";
  /**
   * Path to the resources related to toolbars.
   */
  String TOOLBAR_PATH = "i18n.org.opentcs.plantoverview.toolbar";
  /**
   * Path to the resources related to model properties dialog.
   */
  String MODELPROPERTIES_PATH = "i18n.org.opentcs.plantoverview.dialogs.modelProperties";
  /**
   * Path to the resources related to the modelview panel.
   */
  String MODELVIEW_PATH = "i18n.org.opentcs.plantoverview.panels.modelView";
  /**
   * Path to the resources related to the properties panel.
   */
  String PROPERTIES_PATH = "i18n.org.opentcs.plantoverview.panels.propertyEditing";
  /**
   * Path to the resources related to status messages.
   */
  String STATUS_PATH = "i18n.org.opentcs.plantoverview.panels.status";
  /**
   * Path to the resources related to the tree view.
   */
  String TREEVIEW_PATH = "i18n.org.opentcs.plantoverview.panels.componentTrees";
  /**
   * Path to the resources related to layers.
   */
  String LAYERS_PATH = "i18n.org.opentcs.plantoverview.panels.layers";
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/Enums.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * Provides helper methods for working with enums.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class Enums {

  /**
   * Prevents undesired instantiation.
   */
  private Enums() {
    // Do nada.
  }

  /**
   * Returns the String representations of all elements of the given enum class
   * as a set.
   *
   * @param enumClass The enum class for which to return the String
   * representations.
   * @return The String representations of all elements of the given enum class
   * as a set.
   */
  public static Set<String> asStringSet(Class<? extends Enum<?>> enumClass) {
    Objects.requireNonNull(enumClass, "enumClass is null");

    Set<String> result = new HashSet<>();
    for (Enum<?> constant : enumClass.getEnumConstants()) {
      result.add(constant.name());
    }
    return result;
  }

  /**
   * Returns the String representations of all elements of the given enum class
   * as an array.
   *
   * @param enumClass The enum class for which to return the String
   * representations.
   * @param <E> The enum class's type.
   * @return The String representations of all elements of the given enum class
   * as an array.
   */
  public static <E extends Enum<?>> String[] asStringArray(Class<E> enumClass) {
    Objects.requireNonNull(enumClass, "enumClass is null");

    E[] constants = enumClass.getEnumConstants();
    String[] result = new String[constants.length];
    for (int i = 0; i < result.length; i++) {
      result[i] = constants[i].name();
    }
    return result;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/liner/BezierLinerControlPointHandle.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures.liner;

import java.awt.Point;
import java.util.Objects;
import org.jhotdraw.draw.BezierFigure;
import org.jhotdraw.draw.Drawing;

/**
 * A Handle which allows to interactively change a control point
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class BezierLinerControlPointHandle
    extends org.jhotdraw.draw.handle.BezierControlPointHandle {

  public BezierLinerControlPointHandle(BezierFigure owner, int index, int coord) {
    super(owner, index, coord);
  }

  @Override  // BezierControlPointHandle
  public void trackEnd(Point anchor, Point lead, int modifiersEx) {
    super.trackEnd(anchor, lead, modifiersEx);
    // Fire edit event to update the control points of the Path figure
    Drawing drawing = Objects.requireNonNull(view.getDrawing());
    drawing.fireUndoableEditHappened(new BezierLinerEdit(getBezierFigure()));
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralCommAdapterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.data.model.Location;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;

/**
 * A factory for loopback communication adapters (virtual peripherals).
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralCommAdapterFactory
    implements PeripheralCommAdapterFactory {

  /**
   * The adapter components factory.
   */
  private final LoopbackPeripheralAdapterComponentsFactory componentsFactory;
  /**
   * Indicates whether this component is initialized or not.
   */
  private boolean initialized;

  @Inject
  public LoopbackPeripheralCommAdapterFactory(
      LoopbackPeripheralAdapterComponentsFactory componentsFactory) {
    this.componentsFactory = requireNonNull(componentsFactory, "componentsFactory");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public PeripheralCommAdapterDescription getDescription() {
    return new LoopbackPeripheralCommAdapterDescription();
  }

  @Override
  public boolean providesAdapterFor(Location location) {
    requireNonNull(location, "location");
    return location.getProperties().containsKey(LocationProperties.PROPKEY_LOOPBACK_PERIPHERAL);
  }

  @Override
  public PeripheralCommAdapter getAdapterFor(Location location) {
    requireNonNull(location, "location");
    return componentsFactory.createLoopbackCommAdapter(location.getReference());
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/ValidationEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.EventObject;

/**
 * An event holding a single boolean variable indicating if something is valid.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ValidationEvent
    extends EventObject {

  /**
   * Validation state.
   */
  private final boolean valid;

  /**
   * Create a new <code>ValidationEvent</code>.
   * @param source The source of the event.
   * @param valid The state of validation that should be reported by this event.
   */
  public ValidationEvent(Object source, boolean valid) {
    super(source);
    this.valid = valid;
  }

  /**
   * Return the state of validation.
   * @return valid
   */
  public boolean valid() {
    return valid;
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/PositionableModelComponent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

/**
 * Defines constants for {@link ModelComponent}s that have model coordinates.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PositionableModelComponent
    extends ModelComponent {

  /**
   * Key for the X (model) cordinate.
   */
  public static final String MODEL_X_POSITION = "modelXPosition";
  /**
   * Key for the Y (model) cordinate.
   */
  public static final String MODEL_Y_POSITION = "modelYPosition";
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/StringSetPropertyEditorPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListModel;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.components.properties.type.StringSetProperty;

/**
 * User interface to edit a string set.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class StringSetPropertyEditorPanel
    extends JPanel
    implements DetailsDialogContent {

  /**
   * The property to edit.
   */
  private StringSetProperty fProperty;

  /**
   * Creates new form StringSetPropertyEditorPanel.
   */
  public StringSetPropertyEditorPanel() {
    initComponents();
    setPreferredSize(new Dimension(350, 250));
  }

  @Override
  public void setProperty(Property property) {
    fProperty = (StringSetProperty) property;
    DefaultListModel<String> model = new DefaultListModel<>();

    for (String item : fProperty.getItems()) {
      model.addElement(item);
    }

    itemsList.setModel(model);
  }

  @Override
  public void updateValues() {
    List<String> items = new ArrayList<>();
    ListModel<String> model = itemsList.getModel();
    int size = model.getSize();

    for (int i = 0; i < size; i++) {
      items.add(model.getElementAt(i));
    }

    fProperty.setItems(items);
  }

  @Override
  public Property getProperty() {
    return fProperty;
  }

  /**
   * Edits the selected value.
   */
  protected abstract void edit();

  /**
   * Adds a new entry.
   */
  protected abstract void add();

  /**
   * Returns the list with the values.
   *
   * @return The list with the values.
   */
  protected JList<String> getItemsList() {
    return itemsList;
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    itemsScrollPane = new javax.swing.JScrollPane();
    itemsList = new javax.swing.JList<>();
    controlPanel = new javax.swing.JPanel();
    addButton = new javax.swing.JButton();
    editButton = new javax.swing.JButton();
    removeButton = new javax.swing.JButton();
    rigidArea = new javax.swing.JPanel();
    moveUpButton = new javax.swing.JButton();
    moveDownButton = new javax.swing.JButton();

    setLayout(new java.awt.BorderLayout());

    itemsList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
    itemsScrollPane.setViewportView(itemsList);

    add(itemsScrollPane, java.awt.BorderLayout.CENTER);

    controlPanel.setLayout(new java.awt.GridBagLayout());

    addButton.setFont(addButton.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/panels/propertyEditing"); // NOI18N
    addButton.setText(bundle.getString("stringSetPropertyEditorPanel.button_add.text")); // NOI18N
    addButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        addButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
    controlPanel.add(addButton, gridBagConstraints);

    editButton.setFont(editButton.getFont());
    editButton.setText(bundle.getString("stringSetPropertyEditorPanel.button_edit.text")); // NOI18N
    editButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        editButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(10, 15, 10, 0);
    controlPanel.add(editButton, gridBagConstraints);

    removeButton.setFont(removeButton.getFont());
    removeButton.setText(bundle.getString("stringSetPropertyEditorPanel.button_remove.text")); // NOI18N
    removeButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        removeButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
    controlPanel.add(removeButton, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 5;
    gridBagConstraints.weighty = 1.0;
    controlPanel.add(rigidArea, gridBagConstraints);

    moveUpButton.setFont(moveUpButton.getFont());
    moveUpButton.setText(bundle.getString("stringSetPropertyEditorPanel.button_up.text")); // NOI18N
    moveUpButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        moveUpButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(10, 15, 10, 0);
    controlPanel.add(moveUpButton, gridBagConstraints);

    moveDownButton.setFont(moveDownButton.getFont());
    moveDownButton.setText(bundle.getString("stringSetPropertyEditorPanel.button_down.text")); // NOI18N
    moveDownButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        moveDownButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
    controlPanel.add(moveDownButton, gridBagConstraints);

    add(controlPanel, java.awt.BorderLayout.EAST);
  }// </editor-fold>//GEN-END:initComponents

  private void moveDownButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownButtonActionPerformed
    int index = itemsList.getSelectedIndex();

    if (index == -1) {
      return;
    }

    DefaultListModel<String> model = (DefaultListModel<String>) itemsList.getModel();

    if (index == model.size() - 1) {
      return;
    }

    String value = model.getElementAt(index);
    model.removeElementAt(index);
    model.insertElementAt(value, index + 1);
    itemsList.setSelectedIndex(index + 1);
  }//GEN-LAST:event_moveDownButtonActionPerformed

  private void moveUpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpButtonActionPerformed
    int index = itemsList.getSelectedIndex();

    if (index == -1) {
      return;
    }

    if (index == 0) {
      return;
    }

    DefaultListModel<String> model = (DefaultListModel<String>) itemsList.getModel();
    String value = model.getElementAt(index);
    model.removeElementAt(index);
    model.insertElementAt(value, index - 1);
    itemsList.setSelectedIndex(index - 1);
  }//GEN-LAST:event_moveUpButtonActionPerformed

  private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
    String value = itemsList.getSelectedValue();

    if (value == null) {
      return;
    }

    DefaultListModel<String> model = (DefaultListModel<String>) itemsList.getModel();
    model.removeElement(value);
  }//GEN-LAST:event_removeButtonActionPerformed

  private void editButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editButtonActionPerformed
    edit();
  }//GEN-LAST:event_editButtonActionPerformed

  private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
    add();
  }//GEN-LAST:event_addButtonActionPerformed
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton addButton;
  private javax.swing.JPanel controlPanel;
  private javax.swing.JButton editButton;
  private javax.swing.JList<String> itemsList;
  private javax.swing.JScrollPane itemsScrollPane;
  private javax.swing.JButton moveDownButton;
  private javax.swing.JButton moveUpButton;
  private javax.swing.JButton removeButton;
  private javax.swing.JPanel rigidArea;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/StringPropertyCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Component;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.util.UserMessageHelper;

/**
 * A cell editor for a string property.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class StringPropertyCellEditor
    extends AbstractPropertyCellEditor {

  /**
   * Creates a new instance of StringPropertyCellEditor
   *
   * @param textField
   * @param umh
   */
  public StringPropertyCellEditor(JTextField textField, UserMessageHelper umh) {
    super(textField, umh);
    setStyle(textField);
  }

  /**
   * Initialises the style of the text field.
   *
   * @param textField the text field to style.
   */
  protected final void setStyle(JTextField textField) {
    setClickCountToStart(1);
    textField.setHorizontalAlignment(JTextField.LEFT);
  }

  @Override
  public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {

    setValue(value);
    JTextField textField = (JTextField) getComponent();
    if (value instanceof StringProperty) {
      textField.setDocument(new PlainDocument());
    }
    textField.setText(property().getText());

    return fComponent;
  }

  @Override
  public Object getCellEditorValue() {
    JTextField textField = (JTextField) getComponent();
    String newText = textField.getText();
    String oldText = property().getText();
    property().setText(newText);

    if (!newText.equals(oldText)) {
      markProperty();
    }

    return property();
  }

  /**
   * Returns the property for this editor.
   *
   * @return the property for this editor.
   */
  protected StringProperty property() {
    return (StringProperty) fProperty;
  }

  private class JTextFieldLimit
      extends PlainDocument {

    private final int limit;

    JTextFieldLimit(int limit) {
      super();
      this.limit = limit;
    }

    @Override
    public void insertString(int offset, String str, AttributeSet attr)
        throws BadLocationException {
      if (str == null) {
        return;
      }

      if ((getLength() + str.length()) <= limit || str.equals(getText(0, getLength()))) {
        super.insertString(offset, str, attr);
      }
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/toolbar/MultipleSelectionTool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.toolbar;

import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
import javax.swing.Action;
import javax.swing.JMenuItem;
import org.jhotdraw.draw.tool.DragTracker;
import org.jhotdraw.draw.tool.SelectAreaTracker;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.thirdparty.jhotdraw.application.toolbar.AbstractMultipleSelectionTool;

/**
 * The default selection tool.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class MultipleSelectionTool
    extends AbstractMultipleSelectionTool {
  
  /**
   * Creates a new instance.
   *
   * @param appState Stores the application's current state.
   * @param selectAreaTracker The tracker to be used for area selections in the drawing.
   * @param dragTracker The tracker to be used for dragging figures.
   * @param drawingActions Drawing-related actions for the popup menus created by this tool.
   * @param selectionActions Selection-related actions for the popup menus created by this tool.
   */
  @Inject
  public MultipleSelectionTool(ApplicationState appState,
                               SelectAreaTracker selectAreaTracker,
                               DragTracker dragTracker,
                               @Assisted("drawingActions") Collection<Action> drawingActions,
                               @Assisted("selectionActions") Collection<Action> selectionActions) {
    super(appState, selectAreaTracker, dragTracker, drawingActions, selectionActions);
  }

  @Override
  public List<JMenuItem> customPopupMenuItems() {
    return new ArrayList<>();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/factories/SecureSocketFactoryProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.factories;

import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.rmi.ssl.SslRMIServerSocketFactory;
import org.opentcs.access.SslParameterSet;

/**
 * Provides instances of {@link RMIClientSocketFactory} and {@link RMIServerSocketFactory} that are
 * implemented over the SSL or TLS protocols.
 * Since these factories don't support anonymous cipher suites a keystore on the server-side and a
 * truststore on the client-side is necessary.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SecureSocketFactoryProvider
    implements SocketFactoryProvider {

  /**
   * Provides methods for creating client-side and server-side {@link SSLContext} instances.
   */
  private final SecureSslContextFactory secureSslContextFactory;

  /**
   * Creates a new instance.
   *
   * @param sslParameterSet The SSL parameters to be used for creating socket factories.
   */
  @Inject
  public SecureSocketFactoryProvider(SslParameterSet sslParameterSet) {
    requireNonNull(sslParameterSet, "sslParameterSet");
    this.secureSslContextFactory = new SecureSslContextFactory(sslParameterSet);
  }

  @Override
  public RMIClientSocketFactory getClientSocketFactory() {
    return new CustomSslRMIClientSocketFactory(secureSslContextFactory);
  }

  @Override
  public RMIServerSocketFactory getServerSocketFactory() {
    SSLContext context = secureSslContextFactory.createServerContext();
    SSLParameters param = context.getSupportedSSLParameters();
    return new SslRMIServerSocketFactory(context,
                                         param.getCipherSuites(),
                                         param.getProtocols(),
                                         param.getWantClientAuth());
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/DefaultDispatcherConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import java.util.List;
import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the {@link DefaultDispatcher}
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(DefaultDispatcherConfiguration.PREFIX)
public interface DefaultDispatcherConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "defaultdispatcher";

  @ConfigurationEntry(
      type = "Comma-separated list of strings",
      description = {"Keys by which to prioritize transport orders for assignment.",
                     "Possible values:",
                     "BY_AGE: Sort by age, oldest first.",
                     "BY_DEADLINE: Sort by deadline, most urgent first.",
                     "DEADLINE_AT_RISK_FIRST: Sort orders with deadlines at risk first.",
                     "BY_NAME: Sort by name, lexicographically."},
      orderKey = "0_assign")
  List<String> orderPriorities();

  @ConfigurationEntry(
      type = "Comma-separated list of strings",
      description = {"Keys by which to prioritize vehicles for assignment.",
                     "Possible values:",
                     "BY_ENERGY_LEVEL: Sort by energy level, highest first.",
                     "IDLE_FIRST: Sort vehicles with state IDLE first.",
                     "BY_NAME: Sort by name, lexicographically."},
      orderKey = "0_assign")
  List<String> vehiclePriorities();

  @ConfigurationEntry(
      type = "Comma-separated list of strings",
      description = {"Keys by which to prioritize vehicle candidates for assignment.",
                     "Possible values:",
                     "BY_ENERGY_LEVEL: Sort by energy level of the vehicle, highest first.",
                     "IDLE_FIRST: Sort vehicles with state IDLE first.",
                     "BY_COMPLETE_ROUTING_COSTS: Sort by complete routing costs, lowest first.",
                     "BY_INITIAL_ROUTING_COSTS: Sort by routing costs for the first destination.",
                     "BY_VEHICLE_NAME: Sort by vehicle name, lexicographically."},
      orderKey = "0_assign")
  List<String> vehicleCandidatePriorities();

  @ConfigurationEntry(
      type = "Comma-separated list of strings",
      description = {"Keys by which to prioritize transport order candidates for assignment.",
                     "Possible values:",
                     "BY_AGE: Sort by transport order age, oldest first.",
                     "BY_DEADLINE: Sort by transport order deadline, most urgent first.",
                     "DEADLINE_AT_RISK_FIRST: Sort orders with deadlines at risk first.",
                     "BY_COMPLETE_ROUTING_COSTS: Sort by complete routing costs, lowest first.",
                     "BY_INITIAL_ROUTING_COSTS: Sort by routing costs for the first destination.",
                     "BY_ORDER_NAME: Sort by transport order name, lexicographically."},
      orderKey = "0_assign")
  List<String> orderCandidatePriorities();

  @ConfigurationEntry(
      type = "Integer",
      description = "The time window (in ms) before its deadline in which an order becomes urgent.",
      orderKey = "0_assign_special_0")
  long deadlineAtRiskPeriod();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether orders to the current position with no operation should be assigned.",
      orderKey = "1_orders_special_0")
  boolean assignRedundantOrders();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether unroutable incoming transport orders should be marked as UNROUTABLE.",
      orderKey = "1_orders_special_1")
  boolean dismissUnroutableTransportOrders();

  @ConfigurationEntry(
      type = "String",
      description = {
        "What triggers rerouting of vehicles.",
        "Possible values:",
        "NONE: Rerouting is disabled.",
        "DRIVE_ORDER_FINISHED: Vehicles get rerouted as soon as they finish a drive order.",
        "TOPOLOGY_CHANGE: Vehicles get rerouted immediately on topology changes."
      },
      orderKey = "1_orders_special_2")
  RerouteTrigger rerouteTrigger();

  @ConfigurationEntry(
      type = "String",
      description = {
        "The strategy to use when rerouting of a vehicle results in no route at all.",
        "The vehicle then continues to use the previous route in the configured way.",
        "Possible values:",
        "IGNORE_PATH_LOCKS: Stick to the previous route, ignoring path locks.",
        "PAUSE_IMMEDIATELY: Do not send further orders to the vehicle; wait for another rerouting "
        + "opportunity.",
        "PAUSE_AT_PATH_LOCK: Send further orders to the vehicle only until it reaches a locked "
        + "path; then wait for another rerouting opportunity."
      },
      orderKey = "1_orders_special_3")
  ReroutingImpossibleStrategy reroutingImpossibleStrategy();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to automatically create parking orders for idle vehicles.",
      orderKey = "2_park_0")
  boolean parkIdleVehicles();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to consider parking position priorities when creating parking orders.",
      orderKey = "2_park_1")
  boolean considerParkingPositionPriorities();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to repark vehicles to parking positions with higher priorities.",
      orderKey = "2_park_2")
  boolean reparkVehiclesToHigherPriorityPositions();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to automatically create recharge orders for idle vehicles.",
      orderKey = "3_recharge_0")
  boolean rechargeIdleVehicles();

  @ConfigurationEntry(
      type = "Boolean",
      description = {"Whether vehicles must be recharged until they are fully charged.",
                     "If false, vehicle must only be recharged until sufficiently charged."},
      orderKey = "3_recharge_1")
  boolean keepRechargingUntilFullyCharged();

  @ConfigurationEntry(
      type = "Integer",
      description = "The interval between redispatching of vehicles.",
      orderKey = "9_misc")
  long idleVehicleRedispatchingInterval();

  enum RerouteTrigger {
    NONE,
    DRIVE_ORDER_FINISHED,
    TOPOLOGY_CHANGE;
  }

  enum ReroutingImpossibleStrategy {
    IGNORE_PATH_LOCKS,
    PAUSE_IMMEDIATELY,
    PAUSE_AT_PATH_LOCK;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/LayoutElement.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model.visualization;

import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.TreeMap;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * A generic layout element that is to be displayed.
 *
 * @author <NAME> (Fraunhofer IML)
 * @deprecated Will be removed.
 */
@Deprecated
@ScheduledApiChange(details = "Will be removed.", when = "6.0")
public abstract class LayoutElement
    implements Serializable {

  /**
   * A set of generic key-value pairs associated with this layout element.
   */
  private Map<String, String> properties = new TreeMap<>();
  /**
   * The layer on which this layout element is to be displayed.
   */
  private int layer;

  /**
   * Creates a new LayoutElement.
   */
  protected LayoutElement() {
    // Do nada.
  }

  /**
   * Returns the layer on which this layout element is to be displayed.
   *
   * @return The layer on which this layout element is to be displayed.
   */
  public int getLayer() {
    return layer;
  }

  /**
   * Sets the layer on which this layout element is to be displayed.
   *
   * @param layer The new layer.
   */
  public void setLayer(int layer) {
    this.layer = layer;
  }

  /**
   * Returns this layout element's properties, a generic set of key-value pairs
   * that can contain basically any information describing this element.
   *
   * @return This layout element's properties.
   */
  public Map<String, String> getProperties() {
    return properties;
  }

  /**
   * Sets this layout element's properties.
   *
   * @param properties The new properties.
   */
  public void setProperties(Map<String, String> properties) {
    this.properties = requireNonNull(properties, "properties");
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/OffsetFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import org.jhotdraw.draw.AttributeKeys;
import org.opentcs.guing.components.drawing.course.Origin;

/**
 * An OffsetFigure is an (invisible) figure that moves as the user drags the view
 * beyond its current bounds, so the view becomes larger resp is repainted
 * larger.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OffsetFigure
    extends OriginFigure {
  
  public OffsetFigure() {
    super();
    setModel(new Origin()); // The figure needs a model to work
    set(AttributeKeys.STROKE_COLOR, Color.darkGray);
    setVisible(false);      // only visible for test
  }
  
  @Override
  protected void drawStroke(Graphics2D g) {
    // Shape: "Crosshair" with square
    Rectangle r = (Rectangle) fDisplayBox.clone();

    if (r.width > 0 && r.height > 0) {
      g.drawLine(r.x + r.width / 2, r.y, r.x + r.width / 2, r.y + r.height);
      g.drawLine(r.x, r.y + r.height / 2, r.x + r.width, r.y + r.height / 2);
      r.grow(-4, -4);
      g.drawRect(r.x, r.y, r.width, r.height);
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/guiceConfig/java/org/opentcs/guing/persistence/DefaultPersistenceInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence;

import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import org.opentcs.guing.persistence.unified.UnifiedModelPersistor;
import org.opentcs.guing.persistence.unified.UnifiedModelReader;

/**
 * Default bindings for model readers and persistors.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPersistenceInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {
    bind(OpenTCSModelManagerModeling.class).in(Singleton.class);
    bind(ModelManager.class).to(OpenTCSModelManagerModeling.class);
    bind(ModelManagerModeling.class).to(OpenTCSModelManagerModeling.class);

    bind(ModelFileReader.class).to(UnifiedModelReader.class);
    bind(ModelFilePersistor.class).to(UnifiedModelPersistor.class);
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/edit/DeleteAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.action.edit;

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;
import javax.swing.text.TextAction;
import org.opentcs.guing.components.EditableComponent;
import static org.opentcs.guing.util.I18nPlantOverview.MENU_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Deletes the region at (or after) the caret position.
 * This action acts on the last EditableComponent} / {@code JTextComponent}
 * which had the focus when the {@code ActionEvent} was generated.
 * This action is called when the user selects the "Delete" item in
 * the Edit menu. The menu item is automatically created by the application.
 *
 * @author <NAME>
 */
public class DeleteAction
    extends TextAction {

  public final static String ID = "edit.delete";
  
  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);

  /**
   * Creates a new instance which acts on the currently focused component.
   */
  public DeleteAction() {
    super(ID);

    putValue(NAME, BUNDLE.getString("deleteAction.name"));
    putValue(SHORT_DESCRIPTION, BUNDLE.getString("deleteAction.shortDescription"));
    putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("DEL"));

    ImageIcon image = ImageDirectory.getImageIcon("/menu/edit-delete-2.png");
    putValue(SMALL_ICON, image);
    putValue(LARGE_ICON_KEY, image);
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    Component cFocusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();

    if (cFocusOwner instanceof JComponent) {
      if (cFocusOwner.isEnabled()) {
        if (cFocusOwner instanceof EditableComponent) {
          // Delete all selected UserObjects from the tree or
          // delete all selected Figures from the DrawingView
          ((EditableComponent) cFocusOwner).delete();
        }
        else {
          deleteNextChar(evt);
        }
      }
    }
  }

  /**
   * This method was copied from
   * DefaultEditorKit.DeleteNextCharAction.actionPerformed(ActionEvent).
   *
   * @param e
   */
  public void deleteNextChar(ActionEvent e) {
    JTextComponent c = getTextComponent(e);
    boolean beep = true;

    if ((c != null) && (c.isEditable())) {
      try {
        javax.swing.text.Document doc = c.getDocument();
        Caret caret = c.getCaret();
        int dot = caret.getDot();
        int mark = caret.getMark();

        if (dot != mark) {
          doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
          beep = false;
        }
        else if (dot < doc.getLength()) {
          doc.remove(dot, 1);
          beep = false;
        }
      }
      catch (BadLocationException bl) {
      }
    }

    if (beep) {
      Toolkit.getDefaultToolkit().beep();
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/BasicPeripheralCommAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import static java.util.Objects.requireNonNull;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.drivers.peripherals.management.PeripheralProcessModelEvent;
import org.opentcs.util.event.EventHandler;

/**
 * A base class for peripheral communication adapters mainly providing command queue processing.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class BasicPeripheralCommAdapter
    implements PeripheralCommAdapter {

  /**
   * The handler used to send events to.
   */
  private final EventHandler eventHandler;
  /**
   * A model of the peripheral device's and its communication adapter's attributes.
   */
  private PeripheralProcessModel processModel;
  /**
   * Indicates whether this comm adapter is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param processModel A model of the peripheral device's and its communication adapter's
   * attributes.
   * @param eventHandler The handler used to send events to.
   */
  public BasicPeripheralCommAdapter(PeripheralProcessModel processModel,
                                    EventHandler eventHandler) {
    this.processModel = requireNonNull(processModel, "processModel");
    this.eventHandler = requireNonNull(eventHandler, "eventHandler");
  }

  /**
   * {@inheritDoc}
   * <p>
   * <em>Overriding methods are expected to call this implementation, too.</em>
   * </p>
   */
  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    setProcessModel(getProcessModel().withState(PeripheralInformation.State.UNKNOWN));
    sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  /**
   * {@inheritDoc}
   * <p>
   * <em>Overriding methods are expected to call this implementation, too.</em>
   * </p>
   */
  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    initialized = false;
  }

  /**
   * {@inheritDoc}
   * <p>
   * <em>Overriding methods are expected to call this implementation, too.</em>
   * </p>
   */
  @Override
  public void enable() {
    if (isEnabled()) {
      return;
    }

    connectPeripheral();
    setProcessModel(getProcessModel().withCommAdapterEnabled(true));
    sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.COMM_ADAPTER_ENABLED);
  }

  @Override
  public boolean isEnabled() {
    return processModel.isCommAdapterEnabled();
  }

  /**
   * {@inheritDoc}
   * <p>
   * <em>Overriding methods are expected to call this implementation, too.</em>
   * </p>
   */
  @Override
  public void disable() {
    if (!isEnabled()) {
      return;
    }

    disconnectPeripheral();
    setProcessModel(getProcessModel().withCommAdapterEnabled(false)
        .withState(PeripheralInformation.State.UNKNOWN));
    sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.COMM_ADAPTER_ENABLED);
    sendProcessModelChangedEvent(PeripheralProcessModel.Attribute.STATE);
  }

  @Override
  public PeripheralProcessModel getProcessModel() {
    return processModel;
  }

  protected void setProcessModel(PeripheralProcessModel processModel) {
    this.processModel = processModel;
  }

  protected EventHandler getEventHandler() {
    return eventHandler;
  }

  protected void sendProcessModelChangedEvent(PeripheralProcessModel.Attribute attributeChanged) {
    eventHandler.onEvent(new PeripheralProcessModelEvent(processModel.getLocation(),
                                                         attributeChanged.name(),
                                                         processModel));
  }

  /**
   * Initiates a communication channel to the peripheral device.
   * This method should not block, i.e. it should not wait for the actual connection to be
   * established, as the peripheral device could be temporarily absent or not responding at all.
   * If that's the case, the communication adapter should continue trying to establish a connection
   * until successful or until {@link #disconnectPeripheral()} is called.
   */
  protected abstract void connectPeripheral();

  /**
   * Closes the communication channel to the peripheral device.
   */
  protected abstract void disconnectPeripheral();
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/ClassMatcher.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

/**
 * Checks whether the input argument is assignable to any of a given set of classes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ClassMatcher
    implements Predicate<Object>,
               Serializable {

  /**
   * The set of classes to evaluate incoming events to.
   */
  private final Set<Class<?>> clazzes = new HashSet<>();

  /**
   * Creates a new instance.
   *
   * @param events The set of classes to evaluate incoming events to.
   */
  public ClassMatcher(Class<?>... events) {
    clazzes.addAll(Arrays.asList(events));
  }

  @Override
  public boolean test(Object object) {
    return clazzes.stream().anyMatch(clazz -> clazz.isAssignableFrom(object.getClass()));
  }

  @Override
  public Predicate<Object> negate() {
    return new ClassMatcher() {
      @Override
      public boolean test(Object t) {
        return !ClassMatcher.this.test(t);
      }
    };
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/VehicleTheme.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Vehicle;

/**
 * Provides a vehicle theme.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleTheme {

  /**
   * Returns an image for the given vehicle, disregarding its current state.
   *
   * @param vehicle The vehicle for which to return the image.
   * @return An image for the given vehicle.
   */
  Image statelessImage(@Nonnull Vehicle vehicle);

  /**
   * Returns an image for the given vehicle, representing its current state.
   *
   * @param vehicle The vehicle for which to return the image.
   * @return An image for the given vehicle.
   */
  Image statefulImage(@Nonnull Vehicle vehicle);

  /**
   * Provides a label that describes this vehicle.
   * Usually this is the name of the vehicle or an abbreviation.
   *
   * @param vehicle The vehicle to provide a label for.
   * @return A label that describes the given vehicle.
   */
  String label(Vehicle vehicle);

  /**
   * Provides the vertical offset of the label relative to the center of the vehicle figure.
   *
   * @return The horizontal offset.
   */
  int labelOffsetX();

  /**
   * Provides the vertical offset of the label relative to the center of the vehicle figure.
   *
   * @return The vertical offset.
   */
  int labelOffsetY();

  /**
   * Provides the color to be used for drawing the label.
   *
   * @return The color to be used for drawing the label.
   */
  Color labelColor();

  /**
   * Provides the font to be used for drawing the label.
   *
   * @return The font to be used for drawing the label.
   */
  Font labelFont();
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/action/ToolBarManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action;

import java.net.URL;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.event.ToolAdapter;
import org.jhotdraw.draw.event.ToolEvent;
import org.jhotdraw.draw.event.ToolListener;
import org.opentcs.guing.application.action.actions.CreateTransportOrderAction;
import org.opentcs.guing.application.action.actions.FindVehicleAction;
import org.opentcs.guing.application.action.actions.PauseAllVehiclesAction;
import org.opentcs.guing.application.action.actions.ResumeAllVehiclesAction;
import org.opentcs.guing.application.toolbar.DragTool;
import org.opentcs.guing.application.toolbar.MultipleSelectionTool;
import org.opentcs.guing.application.toolbar.SelectionToolFactory;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.event.ResetInteractionToolCommand;
import org.opentcs.guing.util.CourseObjectFactory;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.application.action.draw.SelectSameAction;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.event.EventHandler;

/**
 * Sets up and manages a list of tool bars in the graphical user interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ToolBarManager
    implements EventHandler {

  /**
   * A factory for selectiont tools.
   */
  private final SelectionToolFactory selectionToolFactory;
  /**
   * A list of all toolbars.
   */
  private final List<JToolBar> toolBarList
      = Collections.synchronizedList(new LinkedList<JToolBar>());
  /**
   * A tool bar for actions creating new items.
   */
  private final JToolBar toolBarCreation = new JToolBar();
  /**
   * A toggle button for the selection tool.
   */
  private final JToggleButton selectionToolButton;
  /**
   * A toggle button for the drag tool.
   */
  private final JToggleButton dragToolButton;
  /**
   * The actual drag tool.
   */
  private DragTool dragTool;
  /**
   * A button for creating transport orders.
   * Available in operating mode.
   */
  private final JButton buttonCreateOrder;
  /**
   * A button for finding vehicles.
   * Available in operating mode.
   */
  private final JButton buttonFindVehicle;
  /**
   * A button for pausing all vehicles.
   * Available in operating mode.
   */
  private final JButton buttonPauseAllVehicles;
  /**
   * A button for resuming all vehicles.
   * Available in operating mode.
   */
  private final JButton buttonResumeAllVehicles;

  /**
   * Creates a new instance.
   *
   * @param actionMap The action map to be used
   * @param crsObjFactory A factory for course objects
   * @param editor The drawing editor
   * @param selectionToolFactory The selection tool factory
   */
  @Inject
  public ToolBarManager(ViewActionMap actionMap,
                        CourseObjectFactory crsObjFactory,
                        OpenTCSDrawingEditor editor,
                        SelectionToolFactory selectionToolFactory) {
    requireNonNull(actionMap, "actionMap");
    requireNonNull(crsObjFactory, "crsObjFactory");
    requireNonNull(editor, "editor");
    this.selectionToolFactory = requireNonNull(selectionToolFactory,
                                               "selectionToolFactory");

    ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TOOLBAR_PATH);

    // --- 1. ToolBar: Creation ---
    // Selection, Drag | Create Point, Location, Path, Link | 
    // Create Location Type, Vehicle, Block, Static Route | 
    // Create Transport Order | Find, Show Vehicles
    toolBarCreation.setActionMap(actionMap);
    // --- Selection Tool ---
    selectionToolButton = addSelectionToolButton(toolBarCreation, editor);
    // --- Drag Tool ---
    dragToolButton = addDragToolButton(toolBarCreation, editor);

    toolBarCreation.addSeparator();

    // --- Create Transport Order (only in Operating mode) ---
    buttonCreateOrder = new JButton(actionMap.get(CreateTransportOrderAction.ID));
    buttonCreateOrder.setText(null);
    toolBarCreation.add(buttonCreateOrder);

    toolBarCreation.addSeparator();

    // --- Find Vehicle (only in Operating mode) ---
    buttonFindVehicle = new JButton(actionMap.get(FindVehicleAction.ID));
    buttonFindVehicle.setText(null);
    toolBarCreation.add(buttonFindVehicle);

    toolBarCreation.addSeparator();

    // --- Pause All Vehicles (only in Operating mode) ---
    buttonPauseAllVehicles = new JButton(actionMap.get(PauseAllVehiclesAction.ID));
    buttonPauseAllVehicles.setText(null);
    toolBarCreation.add(buttonPauseAllVehicles);

    // --- Resume All Vehicles (only in Operating mode) ---
    buttonResumeAllVehicles = new JButton(actionMap.get(ResumeAllVehiclesAction.ID));
    buttonResumeAllVehicles.setText(null);
    toolBarCreation.add(buttonResumeAllVehicles);

    toolBarCreation.setName(labels.getString("toolBarManager.toolbar_drawing.title"));
    toolBarList.add(toolBarCreation);
  }

  public List<JToolBar> getToolBars() {
    return toolBarList;
  }

  public JToolBar getToolBarCreation() {
    return toolBarCreation;
  }

  public JToggleButton getSelectionToolButton() {
    return selectionToolButton;
  }

  public JToggleButton getDragToolButton() {
    return dragToolButton;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof ResetInteractionToolCommand) {
      handleToolReset((ResetInteractionToolCommand) event);
    }
  }

  private void handleToolReset(ResetInteractionToolCommand evt) {
    selectionToolButton.setSelected(true);
  }

  /**
   * Adds the selection tool to the given toolbar.
   *
   * @param toolBar The toolbar to add to.
   * @param editor The DrawingEditor.
   */
  private JToggleButton addSelectionToolButton(JToolBar toolBar,
                                               DrawingEditor editor) {
    LinkedList<Action> drawingActions = new LinkedList<>();
    // Drawing Actions
    drawingActions.add(new SelectSameAction(editor));

    MultipleSelectionTool selectionTool
        = selectionToolFactory.createMultipleSelectionTool(drawingActions, new LinkedList<>());

    ButtonGroup buttonGroup;

    if (toolBar.getClientProperty("toolButtonGroup") instanceof ButtonGroup) {
      buttonGroup = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
    }
    else {
      buttonGroup = new ButtonGroup();
      toolBar.putClientProperty("toolButtonGroup", buttonGroup);
    }

    // Selection tool
    editor.setTool(selectionTool);
    final JToggleButton toggleButton = new JToggleButton();

    if (!(toolBar.getClientProperty("toolHandler") instanceof ToolListener)) {
      ToolListener toolHandler = new ToolAdapter() {
        @Override
        public void toolDone(ToolEvent event) {
          toggleButton.setSelected(true);
        }
      };

      toolBar.putClientProperty("toolHandler", toolHandler);
    }

    toggleButton.setIcon(ImageDirectory.getImageIcon("/toolbar/select-2.png"));
    toggleButton.setText(null);
    toggleButton.setToolTipText(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TOOLBAR_PATH)
        .getString("toolBarManager.button_selectionTool.tooltipText"));

    toggleButton.setSelected(true);
    toggleButton.addItemListener(new ToolButtonListener(selectionTool, editor));
//    toggleButton.setFocusable(false);
    buttonGroup.add(toggleButton);
    toolBar.add(toggleButton);

    return toggleButton;
  }

  /**
   *
   * @param toolBar
   * @param editor
   */
  private JToggleButton addDragToolButton(JToolBar toolBar, DrawingEditor editor) {
    final JToggleButton button = new JToggleButton();
    dragTool = new DragTool();
    editor.setTool(dragTool);

    if (!(toolBar.getClientProperty("toolHandler") instanceof ToolListener)) {
      ToolListener toolHandler = new ToolAdapter() {
        @Override
        public void toolDone(ToolEvent event) {
          button.setSelected(true);
        }
      };
      toolBar.putClientProperty("toolHandler", toolHandler);
    }

    URL url = getClass().getResource(ImageDirectory.DIR + "/toolbar/cursor-opened-hand.png");
    button.setIcon(new ImageIcon(url));
    button.setText(null);
    button.setToolTipText(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TOOLBAR_PATH)
        .getString("toolBarManager.button_dragTool.tooltipText"));

    button.setSelected(false);
    button.addItemListener(new ToolButtonListener(dragTool, editor));
//    button.setFocusable(false);

    ButtonGroup group = (ButtonGroup) toolBar.getClientProperty("toolButtonGroup");
    group.add(button);
    toolBar.add(button);
    return button;
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/layer/NullLayerWrapper.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;

/**
 * A null object for a layer wrapper.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullLayerWrapper
    extends LayerWrapper {

  public NullLayerWrapper() {
    super(new Layer(0, 0, true, "null", 0), new LayerGroup(0, "null", true));
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/action/draw/DefaultPointSelectedAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.draw;

import java.awt.event.ActionEvent;
import static java.util.Objects.requireNonNull;
import javax.swing.AbstractAction;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.action.AbstractSelectedAction;
import org.jhotdraw.draw.tool.CreationTool;
import org.jhotdraw.draw.tool.Tool;
import org.jhotdraw.gui.JPopupButton;
import org.opentcs.guing.components.drawing.figures.LabeledPointFigure;
import org.opentcs.guing.components.drawing.figures.PointFigure;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.util.ImageDirectory;

/**
 * This action manages the behaviour when the user selects the point button.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPointSelectedAction
    extends AbstractSelectedAction {

  /**
   * The SelectionProperty contains all point types in the model.
   */
  private final PointModel.Type pointType;

  private final Tool tool;
  /**
   * The button this action belongs to.
   */
  private final JPopupButton popupButton;
  /**
   * The Icon the popup button uses when this action is selected.
   */
  private final ImageIcon largeIcon;
  /**
   * The ButtonGroup the popupButton belongs to. It is necessary to know it,
   * because
   * <code>DrawingEditor.setTool()</code> doesn't select or deselect the
   * popupButton, so we have to do it manually.
   */
  private final ButtonGroup group;

  /**
   * Constructor for an action of a button in the toolbar.
   *
   * @param editor The drawing editor
   * @param tool The tool
   * @param popupButton The popup button
   * @param group The button group
   */
  public DefaultPointSelectedAction(DrawingEditor editor,
                                    Tool tool,
                                    JPopupButton popupButton,
                                    ButtonGroup group) {
    super(editor);
    this.tool = requireNonNull(tool);
    this.popupButton = requireNonNull(popupButton);
    this.group = requireNonNull(group);

    this.pointType = null;
    this.largeIcon = null;
  }

  /**
   * Constructor for a button inside a drop down menu of another button.
   *
   * @param editor The drawing editor
   * @param tool The tool
   * @param pointType The point type
   * @param popupButton The popup button
   * @param group The button group
   */
  public DefaultPointSelectedAction(DrawingEditor editor,
                                    Tool tool,
                                    PointModel.Type pointType,
                                    JPopupButton popupButton,
                                    ButtonGroup group) {
    super(editor);
    this.pointType = requireNonNull(pointType);
    this.tool = requireNonNull(tool);
    this.popupButton = requireNonNull(popupButton);
    this.group = requireNonNull(group);

    this.largeIcon = getLargeImageIconByType(pointType);

    putValue(AbstractAction.NAME, pointType.getDescription());
    putValue(AbstractAction.SHORT_DESCRIPTION, pointType.getHelptext());
    putValue(AbstractAction.SMALL_ICON, getImageIconByType(pointType));
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    if (pointType != null) {
      CreationTool creationTool = (CreationTool) tool;
      LabeledPointFigure lpf = (LabeledPointFigure) creationTool.getPrototype();
      PointFigure pointFigure = lpf.getPresentationFigure();
      pointFigure.getModel().getPropertyType().setValue(pointType);

      popupButton.setText(null);
      popupButton.setToolTipText(pointType.getHelptext());
      popupButton.setIcon(largeIcon);
    }

    getEditor().setTool(tool);
    group.setSelected(popupButton.getModel(), true);
  }

  @Override
  protected void updateEnabledState() {
    setEnabled(getView() != null && getView().isEnabled());
  }

  private ImageIcon getImageIconByType(PointModel.Type pointType) {
    switch (pointType) {
      case HALT:
        return ImageDirectory.getImageIcon("/toolbar/point-halt.22.png");
      case REPORT:
        return ImageDirectory.getImageIcon("/toolbar/point-report.22.png");
      case PARK:
        return ImageDirectory.getImageIcon("/toolbar/point-park.22.png");
      default:
        return null;
    }
  }

  private ImageIcon getLargeImageIconByType(PointModel.Type pointType) {
    switch (pointType) {
      case HALT:
        return ImageDirectory.getImageIcon("/toolbar/point-halt-arrow.22.png");
      case REPORT:
        return ImageDirectory.getImageIcon("/toolbar/point-report-arrow.22.png");
      case PARK:
        return ImageDirectory.getImageIcon("/toolbar/point-park-arrow.22.png");
      default:
        return null;
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/VehicleCommAdapterPanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.management;

import java.util.List;
import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;

/**
 * Provides comm adapter specific panels used for interaction and displaying information.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleCommAdapterPanelFactory
    extends Lifecycle {

  /**
   * Returns a list of {@link VehicleCommAdapterPanel}s.
   *
   * @param description The description to create panels for.
   * @param vehicle The vehicle to create panels for.
   * @param processModel The current state of the process model a panel may want to initialize its
   * components with.
   * @return A list of comm adapter panels, or an empty list, if this factory cannot provide panels
   * for the given description.
   */
  List<VehicleCommAdapterPanel> getPanelsFor(@Nonnull VehicleCommAdapterDescription description,
                                             @Nonnull TCSObjectReference<Vehicle> vehicle,
                                             @Nonnull VehicleProcessModelTO processModel);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemotePeripheralJobServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * The default implementation of the peripheral job service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemotePeripheralJobServiceProxy
    extends RemoteTCSObjectServiceProxy<RemotePeripheralJobService>
    implements PeripheralJobService {

  @Override
  public PeripheralJob createPeripheralJob(PeripheralJobCreationTO to)
      throws ObjectUnknownException, ObjectExistsException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().createPeripheralJob(getClientId(), to);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/SimpleLineConnection.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.Color;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.EventObject;
import org.jhotdraw.draw.AttributeKey;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.LineConnectionFigure;
import org.jhotdraw.draw.connector.Connector;
import org.jhotdraw.draw.decoration.ArrowTip;
import org.jhotdraw.geom.BezierPath;
import org.opentcs.guing.components.drawing.course.OriginChangeListener;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.AbstractConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class SimpleLineConnection
    extends LineConnectionFigure
    implements ModelBasedFigure,
               AttributesChangeListener,
               OriginChangeListener {

  protected static final AttributeKey<Color> FILL_COLOR
      = new AttributeKey<>("FillColor", Color.class);
  protected static final AttributeKey<Color> STROKE_COLOR
      = new AttributeKey<>("StrokeColor", Color.class);
  protected static final ArrowTip ARROW_FORWARD
      = new ArrowTip(0.35, 12.0, 11.3, true, true, true);
  protected static final ArrowTip ARROW_BACKWARD
      = new ArrowTip(0.35, 12.0, 11.3, true, true, false);
  private static final Logger logger
      = LoggerFactory.getLogger(SimpleLineConnection.class);

  /**
   * Creates a new instance.
   *
   * @param model The model corresponding to this graphical object.
   */
  public SimpleLineConnection(AbstractConnection model) {
    set(FigureConstants.MODEL, model);
    initConnectionFigure();
  }

  /**
   * Initialise this figure.
   */
  protected final void initConnectionFigure() {
    updateDecorations();
  }

  @Override
  public AbstractConnection getModel() {
    return (AbstractConnection) get(FigureConstants.MODEL);
  }

  /**
   * Return the shape.
   *
   * @return the shape.
   */
  public Shape getShape() {
    return path;
  }

  @Override // BezierFigure
  protected BezierPath getCappedPath() {
    // Workaround for NullPointerException in BezierFigure.getCappedPath()
    try {
      return super.getCappedPath();
    }
    catch (NullPointerException ex) {
      logger.warn("", ex);
      return path.clone();
    }
  }

  /**
   * Update the properties of the model.
   */
  public abstract void updateModel();

  /**
   * Scales the model coodinates accodring to changes to the layout scale.
   *
   * @param event The event containing the layout scale change.
   */
  public abstract void scaleModel(EventObject event);

  /**
   * Calculates the euclid distance between the start position and the end position.
   *
   * @param startPosX The x coordiante of the start position.
   * @param startPosY The y coordiante of the start position.
   * @param endPosX The x coordinate of the end position.
   * @param endPosY The y coordinate of the end position.
   * @return the euclid distance between start and end point rounded to the next integer.
   */
  protected double distance(double startPosX, double startPosY, double endPosX, double endPosY) {
    double dX = startPosX - endPosX;
    double dY = startPosY - endPosY;
    double dist = Math.sqrt(dX * dX + dY * dY);
    dist = Math.floor(dist + 0.5);  // round to an integer value.

    return dist;
  }

  public void updateDecorations() {
  }

  @Override // LineConnectionFigure
  protected void handleConnect(Connector start, Connector end) {
    if (start != null && end != null) {
      ModelComponent startModel = start.getOwner().get(FigureConstants.MODEL);
      ModelComponent endModel = end.getOwner().get(FigureConstants.MODEL);
      getModel().setConnectedComponents(startModel, endModel);
      updateModel();
    }
  }

  @Override // LineConnectionFigure
  protected void handleDisconnect(Connector start, Connector end) {
    super.handleDisconnect(start, end);

    getModel().removingConnection();
  }

  @Override // LineConnectionFigure
  public boolean handleMouseClick(Point2D.Double p, MouseEvent evt, DrawingView drawingView) {
    return false;
  }

  @Override // AttributesChangeListener
  public void propertiesChanged(AttributesChangeEvent e) {
    if (!e.getInitiator().equals(this)) {
      updateDecorations();
      fireFigureChanged(getDrawingArea());
    }
  }

  @Override // OriginChangeListener
  public void originLocationChanged(EventObject event) {
  }

  @Override // OriginChangeListener
  public void originScaleChanged(EventObject event) {
    scaleModel(event);
  }

  @Override
  public SimpleLineConnection clone() {
    try {
      SimpleLineConnection clone = (SimpleLineConnection) super.clone();
      clone.set(FigureConstants.MODEL, getModel().clone());

      return clone;
    }
    catch (CloneNotSupportedException exc) {
      throw new IllegalStateException("Unexpected exception encountered", exc);
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/RerouteUtil.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.Route.Step;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.MovementCommand;
import org.opentcs.drivers.vehicle.VehicleController;
import org.opentcs.drivers.vehicle.VehicleControllerPool;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration.ReroutingImpossibleStrategy;
import static org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration.ReroutingImpossibleStrategy.IGNORE_PATH_LOCKS;
import static org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration.ReroutingImpossibleStrategy.PAUSE_AT_PATH_LOCK;
import static org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration.ReroutingImpossibleStrategy.PAUSE_IMMEDIATELY;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides some utility methods used for rerouting vehicles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RerouteUtil {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(RerouteUtil.class);
  /**
   * The router.
   */
  private final Router router;
  /**
   * The vehicle controller pool.
   */
  private final VehicleControllerPool vehicleControllerPool;
  /**
   * The object service.
   */
  private final InternalTransportOrderService transportOrderService;

  private final DefaultDispatcherConfiguration configuration;

  /**
   * Creates a new instance.
   *
   * @param router The router.
   * @param vehicleControllerPool The vehicle controller pool.
   * @param transportOrderService The object service.
   * @param configuration The configuration.
   */
  @Inject
  public RerouteUtil(Router router,
                     VehicleControllerPool vehicleControllerPool,
                     InternalTransportOrderService transportOrderService,
                     DefaultDispatcherConfiguration configuration) {
    this.router = requireNonNull(router, "router");
    this.vehicleControllerPool = requireNonNull(vehicleControllerPool, "vehicleControllerPool");
    this.transportOrderService = requireNonNull(transportOrderService, "transportOrderService");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  public void reroute(Collection<Vehicle> vehicles) {
    for (Vehicle vehicle : vehicles) {
      reroute(vehicle);
    }
  }

  public void reroute(Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");
    LOG.debug("Trying to reroute vehicle '{}'...", vehicle.getName());

    if (!vehicle.isProcessingOrder()) {
      LOG.debug("{} can't be rerouted without processing a transport order.", vehicle.getName());
      return;
    }

    TransportOrder originalOrder = transportOrderService.fetchObject(TransportOrder.class,
                                                                     vehicle.getTransportOrder());

    LOG.debug("{}: Determining the reroute source...", vehicle.getName());
    Point rerouteSource = getFutureOrCurrentPosition(vehicle);

    // Get all unfinished drive order of the transport order the vehicle is processing
    List<DriveOrder> unfinishedOrders = getUnfinishedDriveOrders(originalOrder);

    // Try to get a new route for the unfinished drive orders from the point
    Optional<List<DriveOrder>> optOrders = tryReroute(unfinishedOrders,
                                                      vehicle,
                                                      rerouteSource);

    // Get the drive order with the new route or stick to the old one
    List<DriveOrder> newDriveOrders;
    if (optOrders.isPresent()) {
      newDriveOrders = optOrders.get();
      LOG.debug("Found a new route for {} from point {}: {}",
                vehicle.getName(),
                rerouteSource.getName(),
                newDriveOrders);
    }
    else {
      LOG.debug("Couldn't find a new route for {}. Updating the current one...",
                vehicle.getName());
      unfinishedOrders = updatePathLocks(unfinishedOrders);
      unfinishedOrders
          = markRestrictedSteps(unfinishedOrders,
                                new ExecutionTest(configuration.reroutingImpossibleStrategy(),
                                                  rerouteSource));
      newDriveOrders = unfinishedOrders;
    }

    adjustFirstDriveOrder(newDriveOrders, vehicle, originalOrder, rerouteSource);

    LOG.debug("Updating transport order {}...", originalOrder.getName());
    updateTransportOrder(originalOrder, newDriveOrders, vehicle);
  }

  private void adjustFirstDriveOrder(List<DriveOrder> newDriveOrders,
                                     Vehicle vehicle,
                                     TransportOrder originalOrder,
                                     Point rerouteSource) {
    // If the vehicle is currently processing a (drive) order (and not waiting to get the next
    // drive order) we need to take care of it
    if (vehicle.hasProcState(Vehicle.ProcState.PROCESSING_ORDER)) {
      if (isPointDestinationOfOrder(rerouteSource, originalOrder.getCurrentDriveOrder())) {
        // The current drive order could not get rerouted, because the vehicle already
        // received all commands for it. Therefore we want to keep the original drive order.
        newDriveOrders.set(0, originalOrder.getCurrentDriveOrder());
      }
      else {
        // Restore the current drive order's history
        DriveOrder newCurrentOrder = mergeDriveOrders(originalOrder.getCurrentDriveOrder(),
                                                      newDriveOrders.get(0),
                                                      vehicle);
        newDriveOrders.set(0, newCurrentOrder);
      }
    }
  }

  private void updateTransportOrder(TransportOrder originalOrder,
                                    List<DriveOrder> newDriveOrders,
                                    Vehicle vehicle) {
    VehicleController controller = vehicleControllerPool.getVehicleController(vehicle.getName());

    // Restore the transport order's history
    List<DriveOrder> newOrders = new ArrayList<>();
    newOrders.addAll(originalOrder.getPastDriveOrders());
    newOrders.addAll(newDriveOrders);

    // Update the transport order's drive orders with the re-routed ones
    LOG.debug("{}: Updating drive orders with {}.", originalOrder.getName(), newOrders);
    transportOrderService.updateTransportOrderDriveOrders(originalOrder.getReference(),
                                                          newOrders);

    // If the vehicle is currently processing a (drive) order (and not waiting to get the next
    // drive order) we need to update the vehicle's current drive order with the new one.
    if (vehicle.hasProcState(Vehicle.ProcState.PROCESSING_ORDER)) {
      controller.setTransportOrder(
          transportOrderService.fetchObject(TransportOrder.class, originalOrder.getReference())
      );
    }

    // Let the router know the vehicle selected another route
    router.selectRoute(vehicle, newOrders);
  }

  /**
   * Returns a list of drive orders that yet haven't been finished for the given transport order.
   *
   * @param order The transport order to get unfinished drive orders from.
   * @return The list of unfinished drive orders.
   */
  public List<DriveOrder> getUnfinishedDriveOrders(TransportOrder order) {
    List<DriveOrder> result = new ArrayList<>();
    result.add(order.getCurrentDriveOrder());
    result.addAll(order.getFutureDriveOrders());
    return result;
  }

  /**
   * Merges the two given drive orders.
   * The merged drive order follows the route of orderA to the point where both drive orders
   * (orderA and orderB) start to diverge. From there, the merged drive order follows the route of
   * orderB.
   *
   * @param orderA A drive order.
   * @param orderB A drive order to be merged into {@code orderA}.
   * @param vehicle The vehicle to merge the drive orders for.
   * @return The (new) merged drive order.
   */
  public DriveOrder mergeDriveOrders(DriveOrder orderA, DriveOrder orderB, Vehicle vehicle) {
    // Merge the drive order routes
    Route mergedRoute = mergeRoutes(vehicle, orderA.getRoute(), orderB.getRoute());

    DriveOrder mergedOrder = new DriveOrder(orderA.getDestination())
        .withState(orderA.getState())
        .withTransportOrder(orderA.getTransportOrder())
        .withRoute(mergedRoute);

    return mergedOrder;
  }

  /**
   * Tries to re-route the given drive orders.
   *
   * @param driveOrders The drive orders to re-route.
   * @param vehicle The vehicle to re-route for.
   * @param sourcePoint The source point to re-route from.
   * @return The re-routed list of drive orders, if re-routing is possible, otherwise the original
   * list of drive orders.
   */
  public Optional<List<DriveOrder>> tryReroute(List<DriveOrder> driveOrders,
                                               Vehicle vehicle,
                                               Point sourcePoint) {
    LOG.debug("Trying to reroute drive orders for {} from {}: {}",
              vehicle.getName(),
              sourcePoint,
              driveOrders);
    Optional<List<DriveOrder>> optDriveOrders = router.getRoute(vehicle,
                                                                sourcePoint,
                                                                new TransportOrder("reroute-dummy",
                                                                                   driveOrders));
    return optDriveOrders;
  }

  /**
   * Returns the steps the given vehicle will process in the future after processing the commands
   * that have been already sent to it.
   *
   * @param vehicle The vehicle to get the future steps for.
   * @return The steps the given vehicle will process in the future or an empty list, if the given
   * vehicle isn't processing any order.
   */
  public List<Step> getFutureSteps(Vehicle vehicle) {
    TCSObjectReference<TransportOrder> orderRef = vehicle.getTransportOrder();
    if (orderRef == null) {
      LOG.debug("Vehicle {} isn't processing any order. Can't determine future steps.",
                vehicle.getName());
      return new ArrayList<>();
    }

    TransportOrder order = transportOrderService.fetchObject(TransportOrder.class, orderRef);
    VehicleController controller = vehicleControllerPool.getVehicleController(vehicle.getName());

    // Get the steps for the drive order the vehicle is currently processing
    // The transport order's drive orders and their routes can't be null at this point
    List<Step> currentSteps = order.getCurrentDriveOrder().getRoute().getSteps();

    // If movement commands have been sent to the comm adapter, trim the current steps by these.
    // Movement commands may have not been sent to the comm adapter yet, i.e. if needed resources
    // are already allocated by another vehicle.
    if (!controller.getCommandsSent().isEmpty()) {
      List<MovementCommand> commandsSent = new ArrayList<>(controller.getCommandsSent());
      MovementCommand lastCommandSent = commandsSent.get(commandsSent.size() - 1);

      // Trim the current steps / Get the steps that haven't been sent to the comm adapter yet
      currentSteps = currentSteps.subList(
          currentSteps.indexOf(lastCommandSent.getStep()) + 1, currentSteps.size());
    }

    List<Step> futureSteps = new ArrayList<>();
    futureSteps.addAll(currentSteps);

    // Add the steps from all future drive orders
    order.getFutureDriveOrders().stream()
        .map(driveOrder -> driveOrder.getRoute())
        .map(route -> route.getSteps())
        .forEach(steps -> futureSteps.addAll(steps));

    return futureSteps;
  }

  /**
   * Returns the point the given vehicle will be at after processing all commands that have been
   * or are to be sent to its comm adapter or its current position, if there are no such commands.
   *
   * @param vehicle The vehicle to get the point for.
   * @return The point.
   */
  private Point getFutureOrCurrentPosition(Vehicle vehicle) {
    VehicleController controller = vehicleControllerPool.getVehicleController(vehicle.getName());
    if (controller.getCommandsSent().isEmpty()
        && controller.getInteractionsPendingCommand().isEmpty()) {
      LOG.debug("{}: No commands expected to be executed. Using current position: {}",
                vehicle.getName(),
                vehicle.getCurrentPosition());
      return transportOrderService.fetchObject(Point.class, vehicle.getCurrentPosition());
    }

    if (controller.getInteractionsPendingCommand().isPresent()) {
      LOG.debug(
          "{}: Command with pending peripheral operations present. Using its destination point: {}",
          vehicle.getName(),
          controller.getInteractionsPendingCommand().get().getStep().getDestinationPoint()
      );
      return controller.getInteractionsPendingCommand().get().getStep().getDestinationPoint();
    }

    List<MovementCommand> commandsSent = new ArrayList<>(controller.getCommandsSent());
    MovementCommand lastCommandSent = commandsSent.get(commandsSent.size() - 1);
    LOG.debug("{}: Using the last command sent to the communication adapter: {}",
              vehicle.getName(),
              lastCommandSent);
    return lastCommandSent.getStep().getDestinationPoint();
  }

  /**
   * Checks if the routes of the two given lists of drive orders are equal.
   *
   * @param ordersA A list of drive orders.
   * @param ordersB A list of drive order to be compared with {@code orderA} for equality.
   * @return {@code true} if the rutes are equal to each other and {@code false} otherwise.
   */
  public boolean routesEquals(List<DriveOrder> ordersA, List<DriveOrder> ordersB) {
    List<Route> routesA = ordersA.stream()
        .map(order -> order.getRoute())
        .collect(Collectors.toList());
    List<Route> routesB = ordersB.stream()
        .map(order -> order.getRoute())
        .collect(Collectors.toList());
    return Objects.equals(routesA, routesB);
  }

  private Route mergeRoutes(Vehicle vehicle, Route routeA, Route routeB) {
    // Merge the route steps
    List<Step> mergedSteps = mergeSteps(routeA.getSteps(), routeB.getSteps());

    // Calculate the costs for merged route
    Point sourcePoint = mergedSteps.get(0).getSourcePoint();
    Point destinationPoint = mergedSteps.get(mergedSteps.size() - 1).getDestinationPoint();
    long costs = router.getCosts(vehicle, sourcePoint, destinationPoint);

    return new Route(mergedSteps, costs);
  }

  private List<Step> mergeSteps(List<Step> stepsA, List<Step> stepsB) {
    LOG.debug("Merging steps {} with {}", stepsToPaths(stepsA), stepsToPaths(stepsB));

    // Get the step where routeB starts to depart, i.e. the step where routeA and routeB share the
    // same source point
    Step branchingStep = findStepWithSource(stepsB.get(0).getSourcePoint(), stepsA);

    int branchingIndex = stepsA.indexOf(branchingStep);
    List<Step> mergedSteps = new ArrayList<>();
    mergedSteps.addAll(stepsA.subList(0, branchingIndex));
    mergedSteps.addAll(stepsB);

    // Update the steps route indices since they originate from two different drive orders
    mergedSteps = updateRouteIndices(mergedSteps);

    return mergedSteps;
  }

  private Step findStepWithSource(Point sourcePoint, List<Step> steps) {
    LOG.debug("Looking for a step with source point {} in {}",
              sourcePoint,
              stepsToPaths(steps));
    return steps.stream()
        .filter(step -> Objects.equals(step.getSourcePoint(), sourcePoint))
        .findFirst()
        .get();
  }

  private List<Step> updateRouteIndices(List<Step> steps) {
    List<Step> updatedSteps = new ArrayList<>();
    for (int i = 0; i < steps.size(); i++) {
      Step currStep = steps.get(i);
      updatedSteps.add(new Step(currStep.getPath(),
                                currStep.getSourcePoint(),
                                currStep.getDestinationPoint(),
                                currStep.getVehicleOrientation(),
                                i,
                                currStep.isExecutionAllowed()));
    }
    return updatedSteps;
  }

  private List<Path> stepsToPaths(List<Step> steps) {
    return steps.stream()
        .map(step -> step.getPath())
        .collect(Collectors.toList());
  }

  private boolean isPointDestinationOfOrder(Point point, DriveOrder order) {
    if (point == null || order == null) {
      return false;
    }
    if (order.getRoute() == null) {
      return false;
    }
    return Objects.equals(point, order.getRoute().getFinalDestinationPoint());
  }

  private List<DriveOrder> updatePathLocks(List<DriveOrder> orders) {
    List<DriveOrder> updatedOrders = new ArrayList<>();

    for (DriveOrder order : orders) {
      List<Step> updatedSteps = new ArrayList<>();

      for (Step step : order.getRoute().getSteps()) {
        Path path = transportOrderService.fetchObject(Path.class, step.getPath().getReference());
        updatedSteps.add(new Route.Step(path,
                                        step.getSourcePoint(),
                                        step.getDestinationPoint(),
                                        step.getVehicleOrientation(),
                                        step.getRouteIndex()));
      }

      Route updatedRoute = new Route(updatedSteps, order.getRoute().getCosts());

      DriveOrder updatedOrder = new DriveOrder(order.getDestination())
          .withRoute(updatedRoute)
          .withState(order.getState())
          .withTransportOrder(order.getTransportOrder());
      updatedOrders.add(updatedOrder);
    }

    return updatedOrders;
  }

  private List<DriveOrder> markRestrictedSteps(List<DriveOrder> orders,
                                               Predicate<Step> executionTest) {
    if (configuration.reroutingImpossibleStrategy() == IGNORE_PATH_LOCKS) {
      return orders;
    }
    if (!containsLockedPath(orders)) {
      return orders;
    }

    List<DriveOrder> updatedOrders = new ArrayList<>();
    for (DriveOrder order : orders) {
      List<Step> updatedSteps = new ArrayList<>();

      for (Step step : order.getRoute().getSteps()) {
        boolean executionAllowed = executionTest.test(step);
        LOG.debug("Marking path '{}' allowed: {}", step.getPath(), executionAllowed);
        updatedSteps.add(new Step(step.getPath(),
                                  step.getSourcePoint(),
                                  step.getDestinationPoint(),
                                  step.getVehicleOrientation(),
                                  step.getRouteIndex(),
                                  executionAllowed));
      }

      Route updatedRoute = new Route(updatedSteps, order.getRoute().getCosts());

      DriveOrder updatedOrder = new DriveOrder(order.getDestination())
          .withRoute(updatedRoute)
          .withState(order.getState())
          .withTransportOrder(order.getTransportOrder());
      updatedOrders.add(updatedOrder);
    }

    return updatedOrders;
  }

  private boolean containsLockedPath(List<DriveOrder> orders) {
    return orders.stream()
        .map(order -> order.getRoute().getSteps())
        .flatMap(steps -> steps.stream())
        .anyMatch(step -> step.getPath().isLocked());
  }

  private class ExecutionTest
      implements Predicate<Step> {

    /**
     * The current fallback strategy.
     */
    private final ReroutingImpossibleStrategy strategy;
    /**
     * The (earliest) point from which execution may not be allowed.
     */
    private final Point source;
    /**
     * Whether execution of a step is allowed.
     */
    private boolean executionAllowed = true;

    /**
     * Creates a new intance.
     *
     * @param strategy The current fallback strategy.
     * @param source The (earliest) point from which execution may not be allowed.
     */
    public ExecutionTest(ReroutingImpossibleStrategy strategy, Point source) {
      this.strategy = requireNonNull(strategy, "strategy");
      this.source = requireNonNull(source, "source");
    }

    @Override
    public boolean test(Step step) {
      if (!executionAllowed) {
        return false;
      }

      switch (strategy) {
        case PAUSE_IMMEDIATELY:
          if (Objects.equals(step.getSourcePoint(), source)) {
            executionAllowed = false;
          }
          break;
        case PAUSE_AT_PATH_LOCK:
          if (step.getPath().isLocked()) {
            executionAllowed = false;
          }
          break;
        default:
          executionAllowed = true;
      }

      return executionAllowed;
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/candidate/CandidateComparatorDeadlineAtRiskFirst.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.candidate;

import java.util.Comparator;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorDeadlineAtRiskFirst;

/**
 * Compares {@link AssignmentCandidate}s by their transport order's deadlines, ordering those with a
 * deadline at risk first.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorDeadlineAtRiskFirst
    implements Comparator<AssignmentCandidate> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "DEADLINE_AT_RISK_FIRST";

  /**
   * The comparator that compares the deadlines of transport orders, taking the critical threshold into account.
   */
  private final Comparator<TransportOrder> delegate;

  @Inject
  public CandidateComparatorDeadlineAtRiskFirst(
      TransportOrderComparatorDeadlineAtRiskFirst delegate) {
    this.delegate = requireNonNull(delegate, "delegate");
  }

  /**
   * Compares two candidates by the deadline of their transport order and the given threshold
   * indicating whether the remaining time for the deadline is considered critical
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param candidate1 The first candidate
   * @param candidate2 The second candidate
   * @return the value 0 if the deadlines of candidate1 and candidate2 are both at risk or not;
   * a value less than 0 if only the deadline of candidate1 is at risk
   * and a value greater than 0 in all other cases.
   */
  @Override
  public int compare(AssignmentCandidate candidate1, AssignmentCandidate candidate2) {
    return delegate.compare(candidate1.getTransportOrder(), candidate2.getTransportOrder());
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/test/java/org/opentcs/guing/components/drawing/figures/ToolTipTextGeneratorTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import org.junit.*;
import org.mockito.Mockito;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ToolTipTextGeneratorTest {

  private ModelManager modelManager;

  private ToolTipTextGenerator toolTipTextGenerator;

  @Before
  public void setUp() {
    modelManager = Mockito.mock(ModelManager.class);
    toolTipTextGenerator = new ToolTipTextGenerator(modelManager);
  }

  @Test
  public void sortsPropertiesLexicographically() {
    final String PROP1_KEY = "prop1";
    final String PROP2_KEY = "prop2";
    final String PROP3_KEY = "prop3";
    final String PROP4_KEY = "prop4";

    VehicleModel vehicleModel = new VehicleModel();
    vehicleModel.getPropertyMiscellaneous().addItem(new KeyValueProperty(vehicleModel,
                                                                         PROP4_KEY,
                                                                         "some-value"));
    vehicleModel.getPropertyMiscellaneous().addItem(new KeyValueProperty(vehicleModel,
                                                                         PROP2_KEY,
                                                                         "some-value"));
    vehicleModel.getPropertyMiscellaneous().addItem(new KeyValueProperty(vehicleModel,
                                                                         PROP3_KEY,
                                                                         "some-value"));
    vehicleModel.getPropertyMiscellaneous().addItem(new KeyValueProperty(vehicleModel,
                                                                         PROP1_KEY,
                                                                         "some-value"));

    String toolTipText = toolTipTextGenerator.getToolTipText(vehicleModel);

    assertThat(toolTipText.indexOf(PROP1_KEY), is(lessThan(toolTipText.indexOf(PROP2_KEY))));
    assertThat(toolTipText.indexOf(PROP2_KEY), is(lessThan(toolTipText.indexOf(PROP3_KEY))));
    assertThat(toolTipText.indexOf(PROP3_KEY), is(lessThan(toolTipText.indexOf(PROP4_KEY))));
  }
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/peripherals/PeripheralDetailPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.peripherals;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import org.opentcs.components.Lifecycle;
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanel;
import org.opentcs.drivers.peripherals.management.PeripheralCommAdapterPanelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Displays the comm adapter panels for a given peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralDetailPanel
    extends JPanel
    implements PropertyChangeListener,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralDetailPanel.class);
  /**
   * A panel's default border title.
   */
  private static final String DEFAULT_BORDER_TITLE = "";
  /**
   * The adapter specific list of panels.
   */
  private final List<PeripheralCommAdapterPanel> customPanelList = new LinkedList<>();
  /**
   * The set of factories to create adapter specific panels with.
   */
  private final Set<PeripheralCommAdapterPanelFactory> panelFactories;
  /**
   * The peripheral device that is currently associated with/being displayed in this panel.
   */
  private LocalPeripheralEntry peripheralEntry;
  /**
   * Whether this panel is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param panelFactories The factories to create adapter specific panels with.
   */
  @Inject
  public PeripheralDetailPanel(Set<PeripheralCommAdapterPanelFactory> panelFactories) {
    this.panelFactories = requireNonNull(panelFactories, "panelFactories");

    initComponents();

    // Make sure we start with an empty panel.
    detachFromEntry();
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    for (PeripheralCommAdapterPanelFactory panelFactory : panelFactories) {
      panelFactory.initialize();
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    detachFromEntry();

    for (PeripheralCommAdapterPanelFactory panelFactory : panelFactories) {
      panelFactory.terminate();
    }

    initialized = false;
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if (!(evt.getSource() instanceof LocalPeripheralEntry)) {
      return;
    }

    LocalPeripheralEntry entry = (LocalPeripheralEntry) evt.getSource();
    if (!Objects.equals(entry, peripheralEntry)) {
      // Since we're registered only to the currently selected/attached entry, this should never 
      // happen.
      return;
    }

    if (Objects.equals(evt.getPropertyName(), LocalPeripheralEntry.Attribute.PROCESS_MODEL.name())) {
      for (PeripheralCommAdapterPanel panel : customPanelList) {
        panel.processModelChanged(entry.getProcessModel());
      }
    }
  }

  /**
   * Attaches this panel to a peripheral device.
   *
   * @param newPeripheralEntry The peripheral entry to attach to.
   */
  public void attachToEntry(LocalPeripheralEntry newPeripheralEntry) {
    requireNonNull(newPeripheralEntry, "newPeripheralEntry");

    // Clean up first - but only if we're not reattaching to the same entry.
    if (peripheralEntry != newPeripheralEntry) {
      detachFromEntry();
    }
    peripheralEntry = newPeripheralEntry;

    setBorderTitle(peripheralEntry.getProcessModel().getLocation().getName());

    // Ensure the tabbed pane containing peripheral information is shown.
    removeAll();
    add(tabbedPane);

    updateCustomPanels();

    // Update panel contents.
    validate();
    if (!customPanelList.isEmpty()) {
      tabbedPane.setSelectedIndex(0);
    }

    peripheralEntry.addPropertyChangeListener(this);
  }

  /**
   * Detaches this panel from a peripheral device (if it is currently attached to any).
   */
  private void detachFromEntry() {
    if (peripheralEntry != null) {
      peripheralEntry.removePropertyChangeListener(this);
      removeAndClearCustomPanels();
      peripheralEntry = null;
    }
    setBorderTitle(DEFAULT_BORDER_TITLE);
    // Remove the contents of this panel.
    removeAll();
    add(noPeripheralDevicePanel);
    // Update panel contents.
    validate();
  }

  /**
   * Removes the custom panels from this panel's tabbed pane.
   */
  private void removeAndClearCustomPanels() {
    for (PeripheralCommAdapterPanel panel : customPanelList) {
      LOG.debug("Removing {} from tabbedPane.", panel);
      tabbedPane.remove(panel);
    }

    customPanelList.clear();
  }

  /**
   * Update the list of custom panels in the tabbed pane.
   */
  private void updateCustomPanels() {
    removeAndClearCustomPanels();

    if (peripheralEntry == null) {
      return;
    }

    for (PeripheralCommAdapterPanelFactory panelFactory : panelFactories) {
      customPanelList.addAll(panelFactory.getPanelsFor(peripheralEntry.getAttachedCommAdapter(),
                                                       peripheralEntry.getLocation(),
                                                       peripheralEntry.getProcessModel()));
    }

    for (PeripheralCommAdapterPanel curPanel : customPanelList) {
      LOG.debug("Adding {} with title {} to tabbedPane.", curPanel, curPanel.getTitle());
      tabbedPane.addTab(curPanel.getTitle(), curPanel);
    }
  }

  /**
   * Sets this panel's border title.
   *
   * @param title This panel's new border title.
   */
  private void setBorderTitle(String title) {
    requireNonNull(title, "title");
    ((TitledBorder) getBorder()).setTitle(title);
    // Trigger a repaint - the title sometimes looks strange otherwise.
    repaint();
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    noPeripheralDevicePanel = new javax.swing.JPanel();
    noPeripheralDeviceLabel = new javax.swing.JLabel();
    tabbedPane = new javax.swing.JTabbedPane();

    noPeripheralDevicePanel.setLayout(new java.awt.BorderLayout());

    noPeripheralDeviceLabel.setFont(noPeripheralDeviceLabel.getFont().deriveFont(noPeripheralDeviceLabel.getFont().getSize()+3f));
    noPeripheralDeviceLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/kernelcontrolcenter/Bundle"); // NOI18N
    noPeripheralDeviceLabel.setText(bundle.getString("peripheralDetailPanel.label_noPeripheralDeviceAttached.text")); // NOI18N
    noPeripheralDevicePanel.add(noPeripheralDeviceLabel, java.awt.BorderLayout.CENTER);

    setBorder(javax.swing.BorderFactory.createTitledBorder(DEFAULT_BORDER_TITLE));
    setLayout(new java.awt.BorderLayout());

    tabbedPane.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT);
    add(tabbedPane, java.awt.BorderLayout.CENTER);
  }// </editor-fold>//GEN-END:initComponents

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JLabel noPeripheralDeviceLabel;
  private javax.swing.JPanel noPeripheralDevicePanel;
  private javax.swing.JTabbedPane tabbedPane;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON

}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/KernelClientApplication.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

import org.opentcs.components.Lifecycle;

/**
 * Provides methods used in a kernel client application's context.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface KernelClientApplication
    extends Lifecycle {

  /**
   * Tells the application to switch its state to online.
   *
   * @param autoConnect Whether to connect automatically to the kernel or to show a connect dialog 
   * when going online.
   */
  public void online(boolean autoConnect);

  /**
   * Tells the application to switch its state to offline.
   */
  public void offline();

  /**
   * Checks whether the application's state is online.
   *
   * @return Whether the application's state is online.
   */
  public boolean isOnline();

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralCommAdapterDescription.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import java.io.Serializable;
import javax.annotation.Nonnull;

/**
 * Provides the description for a peripheral communication adapter.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class PeripheralCommAdapterDescription
    implements Serializable {

  /**
   * Returns the description for a peripheral communication adapter.
   *
   * @return The description for a peripheral communication adapter.
   */
  @Nonnull
  public abstract String getDescription();

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof PeripheralCommAdapterDescription)) {
      return false;
    }

    return getDescription().equals(((PeripheralCommAdapterDescription) obj).getDescription());
  }

  @Override
  public int hashCode() {
    return getDescription().hashCode();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/draw/SelectSameAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 * Changed by IML to allow access to ResourceBundle.
 *
 *
 * @(#)SelectSameAction.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.application.action.draw;

import java.util.HashSet;
import java.util.Set;
import static javax.swing.Action.SMALL_ICON;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.action.AbstractSelectedAction;
import static org.opentcs.guing.util.I18nPlantOverview.MODELVIEW_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * SelectSameAction.
 *
 * @author <NAME>
 */
public class SelectSameAction
    extends AbstractSelectedAction {

  public final static String ID = "edit.selectSame";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MODELVIEW_PATH);

  /**
   * Creates a new instance.
   *
   * @param editor The drawing editor
   */
  public SelectSameAction(DrawingEditor editor) {
    super(editor);

    putValue(NAME, BUNDLE.getString("selectSameAction.name"));
    putValue(SMALL_ICON, ImageDirectory.getImageIcon("/menu/kcharselect.png"));

    updateEnabledState();
  }

  @Override
  public void actionPerformed(java.awt.event.ActionEvent e) {
    selectSame();
  }

  public void selectSame() {
    Set<Class<?>> selectedClasses = new HashSet<>();

    for (Figure selected : getView().getSelectedFigures()) {
      selectedClasses.add(selected.getClass());
    }

    for (Figure f : getDrawing().getChildren()) {
      if (selectedClasses.contains(f.getClass())) {
        getView().addToSelection(f);
      }
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/peripherals/PeripheralOperation.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.peripherals;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;

/**
 * Describes an operation that is to be executed by a peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralOperation
    implements Serializable {

  /**
   * The location the peripheral device is associated with.
   */
  @Nonnull
  private final TCSResourceReference<Location> location;
  /**
   * The actual operation to be executed by the peripheral device.
   */
  @Nonnull
  private final String operation;
  /**
   * The moment at which this operation is to be executed.
   */
  @Nonnull
  private final ExecutionTrigger executionTrigger;
  /**
   * Whether the completion of this operation is required to allow a vehicle to continue driving.
   */
  private final boolean completionRequired;

  /**
   * Creates a new instance.
   *
   * @param location The location the peripheral device is associated with.
   * @param operation The actual operation to be executed by the peripheral device.
   * @param executionTrigger The moment at which this operation is to be executed.
   * @param completionRequired Whether the completion of this operation is required to allow a
   * vehicle to continue driving.
   */
  public PeripheralOperation(@Nonnull TCSResourceReference<Location> location,
                             @Nonnull String operation,
                             @Nonnull ExecutionTrigger executionTrigger,
                             boolean completionRequired) {
    this.location = requireNonNull(location, "location");
    this.operation = requireNonNull(operation, "operation");
    this.executionTrigger = requireNonNull(executionTrigger, "executionTrigger");
    this.completionRequired = completionRequired;
  }

  /**
   * Returns the location the peripheral device is associated with.
   *
   * @return The location the peripheral device is associated with.
   */
  @Nonnull
  public TCSResourceReference<Location> getLocation() {
    return location;
  }

  /**
   * Returns the actual operation to be executed by the peripheral device.
   *
   * @return The actual operation to be executed by the peripheral device.
   */
  @Nonnull
  public String getOperation() {
    return operation;
  }

  /**
   * Returns the moment at which this operation is to be executed.
   *
   * @return The moment at which this operation is to be executed.
   */
  @Nonnull
  public ExecutionTrigger getExecutionTrigger() {
    return executionTrigger;
  }

  /**
   * Returns whether the completion of this operation is required to allow a vehicle to continue
   * driving.
   *
   * @return Whether the completion of this operation is required to allow a vehicle to continue
   * driving.
   */
  public boolean isCompletionRequired() {
    return completionRequired;
  }

  /**
   * Defines the various moments at which an operation may be executed.
   */
  public static enum ExecutionTrigger {
    BEFORE_MOVEMENT,
    AFTER_MOVEMENT;
  }

  @Override
  public String toString() {
    return "PeripheralOperation{"
        + "location=" + location + ", "
        + "operation=" + operation + ", "
        + "executionTrigger=" + executionTrigger + ", "
        + "completionRequired=" + completionRequired + '}';
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/phase/AssignReservedPeripheralsPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching.phase;

import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralControllerPool;
import org.opentcs.strategies.basic.peripherals.dispatching.PeripheralDispatcherPhase;
import org.opentcs.strategies.basic.peripherals.dispatching.PeripheralJobUtil;
import org.opentcs.util.Comparators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Assigns the next peripheral job that matches a peripheral's reservation token to peripherals that
 * are currently not processing any.
 * Peripherals with no reservation token set are not cosidered in this phase.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignReservedPeripheralsPhase
    implements PeripheralDispatcherPhase {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AssignReservedPeripheralsPhase.class);
  /**
   * The object service.
   */
  private final TCSObjectService objectService;
  /**
   * The peripheral controller pool.
   */
  private final PeripheralControllerPool peripheralControllerPool;
  /**
   * Provides service functions for working with peripheral jobs and their states.
   */
  private final PeripheralJobUtil peripheralJobUtil;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public AssignReservedPeripheralsPhase(TCSObjectService objectService,
                                        PeripheralControllerPool peripheralControllerPool,
                                        PeripheralJobUtil peripheralJobUtil) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.peripheralControllerPool = requireNonNull(peripheralControllerPool,
                                                   "peripheralControllerPool");
    this.peripheralJobUtil = requireNonNull(peripheralJobUtil, "peripheralJobUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    for (Location location : objectService.fetchObjects(Location.class,
                                                        this::reservedAndAvailable)) {
      checkForReservedJobs(location);
    }
  }

  private boolean reservedAndAvailable(Location location) {
    return processesNoJob(location) && hasReservationToken(location);
  }

  private boolean processesNoJob(Location location) {
    return location.getPeripheralInformation().getProcState()
        == PeripheralInformation.ProcState.IDLE
        && location.getPeripheralInformation().getState()
        == PeripheralInformation.State.IDLE;
  }

  private boolean hasReservationToken(Location location) {
    return location.getPeripheralInformation().getReservationToken() != null;
  }

  private void checkForReservedJobs(Location location) {
    objectService.fetchObjects(PeripheralJob.class, this::toBeProcessed).stream()
        .filter(job -> matchesReservationToken(job, location))
        .filter(job -> matchesLocation(job, location))
        .filter(job -> canProcess(location, job))
        .sorted(Comparators.jobsByAge())
        .findFirst()
        .ifPresent(job -> assignJob(job, location));
  }

  private boolean toBeProcessed(PeripheralJob job) {
    return job.getState() == PeripheralJob.State.TO_BE_PROCESSED;
  }

  private boolean matchesReservationToken(PeripheralJob job, Location location) {
    return Objects.equals(job.getReservationToken(),
                          location.getPeripheralInformation().getReservationToken());
  }

  private boolean matchesLocation(PeripheralJob job, Location location) {
    return Objects.equals(job.getPeripheralOperation().getLocation(),
                          location.getReference());
  }

  private boolean canProcess(Location location, PeripheralJob job) {
    return peripheralControllerPool.getPeripheralController(location.getReference())
        .canProcess(job).getValue();
  }

  private void assignJob(PeripheralJob job, Location location) {
    LOG.debug("Assigning job '{}' to peripheral '{}'...", job.getName(), location.getName());
    peripheralJobUtil.assignPeripheralJob(location, job);
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/Comparators.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.util.Comparator;

/**
 * Some comparator implementations for JAXB classes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class Comparators {

  /**
   * A <code>Comparator</code> for ordering <code>PlantModelElementTO</code>s ascendingly by their
   * names.
   */
  private static final Comparator<PlantModelElementTO> ELEMENTS_BY_NAME
      = (PlantModelElementTO o1, PlantModelElementTO o2) -> o1.getName().compareTo(o2.getName());
  /**
   * A <code>Comparator</code> for ordering <code>OutgoingPath</code>s ascendingly by their names.
   */
  private static final Comparator<PointTO.OutgoingPath> OUTGOING_PATHS_BY_NAME
      = (PointTO.OutgoingPath o1, PointTO.OutgoingPath o2) -> o1.getName().compareTo(o2.getName());
  /**
   * A <code>Comparator</code> for ordering <code>Link</code>s ascendingly by their point names.
   */
  private static final Comparator<LocationTO.Link> LINKS_BY_POINT_NAME
      = (LocationTO.Link o1, LocationTO.Link o2) -> o1.getPoint().compareTo(o2.getPoint());
  /**
   * A <code>Comparator</code> for ordering <code>Properties</code> ascendingly by their
   * names.
   */
  private static final Comparator<PropertyTO> PROPERTIES_BY_NAME
      = (PropertyTO o1, PropertyTO o2) -> o1.getName().compareTo(o2.getName());

  private Comparators() {
  }

  /**
   * Returns a comparator for ordering <code>PlantModelElementTO</code>s ascendingly by their names.
   *
   * @return A comparator for ordering <code>PlantModelElementTO</code>s ascendingly by their names.
   */
  public static Comparator<PlantModelElementTO> elementsByName() {
    return ELEMENTS_BY_NAME;
  }

  /**
   * Returns a comparator for ordering <code>OutgoingPath</code>s ascendingly by their names.
   *
   * @return A comparator for ordering <code>OutgoingPath</code>s ascendingly by their names.
   */
  public static Comparator<PointTO.OutgoingPath> outgoingPathsByName() {
    return OUTGOING_PATHS_BY_NAME;
  }

  /**
   * Returns a comparator for ordering <code>Link</code>s ascendingly by their point names.
   *
   * @return A comparator for ordering <code>Link</code>s ascendingly by their point names.
   */
  public static Comparator<LocationTO.Link> linksByPointName() {
    return LINKS_BY_POINT_NAME;
  }

  /**
   * Returns a comparator for ordering <code>Properties</code>s ascendingly by their names.
   *
   * @return A comparator for ordering <code>Properties</code> ascendingly by their names.
   */
  public static Comparator<PropertyTO> propertiesByName() {
    return PROPERTIES_BY_NAME;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/PanelRegistry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A registry for all plugin panel factories.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PanelRegistry {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PanelRegistry.class);
  /**
   * The registered factories.
   */
  private final List<PluggablePanelFactory> factories = new LinkedList<>();

  /**
   * Creates a new instance.
   *
   * @param factories The factories.
   */
  @Inject
  public PanelRegistry(Set<PluggablePanelFactory> factories) {
    requireNonNull(factories, "factories");

    // Auto-detect generic client panel factories.
    for (PluggablePanelFactory factory : factories) {
      LOG.info("Setting up plugin panel factory: {}", factory.getClass().getName());
      this.factories.add(factory);
    }
    if (this.factories.isEmpty()) {
      LOG.info("No plugin panel factories found.");
    }
  }

  /**
   * Returns the registered factories.
   *
   * @return The registered factories.
   */
  public List<PluggablePanelFactory> getFactories() {
    return new LinkedList<>(factories);
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/NumberParsers.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * Provides methods for optimized parsing of numbers from character sequences.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class NumberParsers {

  /**
   * The number of characters used for <code>Long.MAX_VALUE</code>.
   */
  private static final int MAX_POSITIVE_LONG_CHARS = Long.toString(Long.MAX_VALUE).length();
  /**
   * The number of characters used for <code>Long.MIN_VALUE</code>.
   */
  private static final int MAX_NEGATIVE_LONG_CHARS = Long.toString(Long.MIN_VALUE).length();

  /**
   * Prevents creation of instances of this class.
   */
  private NumberParsers() {
  }

  /**
   * Parses a sequence of characters as a decimal number and returns the latter.
   *
   * @param source The character sequence to be parsed.
   * @return The decimal number represented by the given character sequence.
   * @throws NumberFormatException If the parsed sequence of characters does not
   * represent a decimal number.
   */
  public static long parsePureDecimalLong(CharSequence source)
      throws NumberFormatException {
    return parsePureDecimalLong(source, 0, source.length());
  }

  /**
   * Parses a (sub)sequence of characters as a decimal number and returns the
   * latter.
   *
   * @param source The character sequence to be parsed.
   * @param startIndex The position at which to start parsing.
   * @param length The number of characters to parse.
   * @return The decimal number represented by the given character sequence.
   * @throws NumberFormatException If the parsed sequence of characters does not
   * represent a decimal number.
   */
  public static long parsePureDecimalLong(CharSequence source, int startIndex,
                                          int length)
      throws NumberFormatException {
    requireNonNull(source, "source");
    checkInRange(startIndex, 0, source.length() - 1, "startIndex");
    checkInRange(length, 1, Integer.MAX_VALUE, "length");

    long result = 0;
    int index = 0;
    boolean negative;
    long limit;
    // Check if we have a negative number and initialize accordingly.
    if (source.charAt(startIndex) == '-') {
      if (length > MAX_NEGATIVE_LONG_CHARS) {
        throw new NumberFormatException("too long to be parsed");
      }
      negative = true;
      limit = Long.MIN_VALUE;
      index++;
    }
    else {
      if (length > MAX_POSITIVE_LONG_CHARS) {
        throw new NumberFormatException("too long to be parsed");
      }
      negative = false;
      limit = -Long.MAX_VALUE;
    }
    while (index < length) {
      int digit = source.charAt(startIndex + index) - '0';
      // If we've just read something other than a digit, throw an exception.
      if (digit < 0 || digit > 9) {
        throw new NumberFormatException(
            "not a decimal digit: " + source.charAt(startIndex + index));
      }
      result *= 10;
      // Check if the next operation would overflow the result.
      if (result < limit + digit) {
        throw new NumberFormatException(
            "parsed number exceeds value boundaries");
      }
      result -= digit;
      index++;
    }
    if (negative) {
      // If we did not parse at least one digit, throw an exception.
      if (index < 2) {
        throw new NumberFormatException("minus sign without succeeding digits");
      }
      return result;
    }
    else {
      return -result;
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/KernelStateModelling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.components.kernel.KernelExtension;
import org.opentcs.customizations.kernel.ActiveInModellingMode;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.kernel.persistence.ModelPersister;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.TCSObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class implements the standard openTCS kernel in modelling mode.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class KernelStateModelling
    extends KernelStateOnline {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(KernelStateModelling.class);
  /**
   * This kernel state's local extensions.
   */
  private final Set<KernelExtension> extensions;
  /**
   * This instance's <em>initialized</em> flag.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param objectPool The object pool to be used.
   * @param model The model to be used.
   * @param modelPersister The model persister to be used.
   * @param configuration This class's configuration.
   * @param extensions The kernel extensions to be used.
   */
  @Inject
  KernelStateModelling(@GlobalSyncObject Object globalSyncObject,
                       TCSObjectPool objectPool,
                       Model model,
                       ModelPersister modelPersister,
                       KernelApplicationConfiguration configuration,
                       @ActiveInModellingMode Set<KernelExtension> extensions) {
    super(globalSyncObject,
          objectPool,
          model,
          modelPersister,
          configuration.saveModelOnTerminateModelling());
    this.extensions = requireNonNull(extensions, "extensions");
  }

  @Override
  public void initialize() {
    if (initialized) {
      throw new IllegalStateException("Already initialized");
    }
    LOG.debug("Initializing modelling state...");

    // Start kernel extensions.
    for (KernelExtension extension : extensions) {
      LOG.debug("Initializing kernel extension '{}'...", extension);
      extension.initialize();
    }
    LOG.debug("Finished initializing kernel extensions.");

    initialized = true;

    LOG.debug("Modelling state initialized.");
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!initialized) {
      throw new IllegalStateException("Not initialized, cannot terminate");
    }
    LOG.debug("Terminating modelling state...");
    super.terminate();

    // Terminate everything that may still use resources.
    for (KernelExtension extension : extensions) {
      LOG.debug("Terminating kernel extension '{}'...", extension);
      extension.terminate();
    }
    LOG.debug("Terminated kernel extensions.");

    initialized = false;

    LOG.debug("Modelling state terminated.");
  }

  @Override
  public Kernel.State getState() {
    return Kernel.State.MODELLING;
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/V004ModelParser.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.awt.Color;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.opentcs.access.to.model.PlantModelCreationTO;
import static org.opentcs.data.ObjectPropConstants.LOCTYPE_DEFAULT_REPRESENTATION;
import static org.opentcs.data.ObjectPropConstants.LOC_DEFAULT_REPRESENTATION;
import org.opentcs.data.model.ModelConstants;
import org.opentcs.data.model.visualization.ElementPropKeys;
import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.util.Colors;
import org.opentcs.util.persistence.v003.V003ModelParser;
import org.opentcs.util.persistence.v003.V003PlantModelTO;
import org.opentcs.util.persistence.v003.VisualLayoutTO.ModelLayoutElement;

/**
 * The parser for V004 models.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V004ModelParser {

  /**
   * Reads a model with the given reader and parses it to a {@link PlantModelCreationTO} instance.
   *
   * @param reader The reader to use.
   * @param modelVersion The model version.
   * @return The parsed {@link PlantModelCreationTO}.
   * @throws IOException If there was an error reading the model.
   */
  public PlantModelCreationTO read(Reader reader, String modelVersion)
      throws IOException {
    return new V004TOMapper().map(readRaw(reader, modelVersion));
  }

  /**
   * Reads a model with the given reader and parses it to a {@link V004PlantModelTO} instance.
   *
   * @param reader The reader to use.
   * @param modelVersion The model version.
   * @return The parsed {@link V004PlantModelTO}.
   * @throws IOException If there was an error reading the model.
   */
  public V004PlantModelTO readRaw(Reader reader, String modelVersion)
      throws IOException {
    if (Objects.equals(modelVersion, V004TOMapper.VERSION_STRING)) {
      return V004PlantModelTO.fromXml(reader);
    }
    else {
      return convert(new V003ModelParser().readRaw(reader, modelVersion));
    }
  }

  private V004PlantModelTO convert(V003PlantModelTO to) {
    Map<String, ModelLayoutElement> modelLayoutElementMap = getModelLayoutElementMap(to);

    V004PlantModelTO result = new V004PlantModelTO()
        .setName(to.getName())
        .setPoints(convertPoints(to, modelLayoutElementMap))
        .setPaths(convertPaths(to, modelLayoutElementMap))
        .setVehicles(convertVehicles(to, modelLayoutElementMap))
        .setLocationTypes(convertLocationTypes(to))
        .setLocations(convertLocations(to, modelLayoutElementMap))
        .setBlocks(convertBlocks(to, modelLayoutElementMap))
        .setVisualLayout(convertVisualLayout(to))
        .setProperties(convertProperties(to.getProperties()));

    return assignElementsToDefaultLayer(result);
  }

  private Map<String, ModelLayoutElement> getModelLayoutElementMap(
      V003PlantModelTO to) {
    Map<String, ModelLayoutElement> result = new HashMap<>();
    for (ModelLayoutElement mle : to.getVisualLayouts().get(0).getModelLayoutElements()) {
      result.put(mle.getVisualizedObjectName(), mle);
    }
    return result;
  }

  private List<PropertyTO> convertProperties(
      List<org.opentcs.util.persistence.v003.PropertyTO> tos) {
    return tos.stream()
        .map(property -> new PropertyTO().setName(property.getName()).setValue(property.getValue()))
        .collect(Collectors.toList());
  }

  private V004PlantModelTO assignElementsToDefaultLayer(V004PlantModelTO model) {
    List<PointTO> pointsAssignedToDefaultLayer = new ArrayList<>();
    for (PointTO point : model.getPoints()) {
      pointsAssignedToDefaultLayer.add(
          point.setPointLayout(point.getPointLayout().setLayerId(ModelConstants.DEFAULT_LAYER_ID))
      );
    }

    List<PathTO> pathsAssignedToDefaultLayer = new ArrayList<>();
    for (PathTO path : model.getPaths()) {
      pathsAssignedToDefaultLayer.add(
          path.setPathLayout(path.getPathLayout().setLayerId(ModelConstants.DEFAULT_LAYER_ID))
      );
    }

    List<LocationTO> locationsAssignedToDefaultLayer = new ArrayList<>();
    for (LocationTO path : model.getLocations()) {
      locationsAssignedToDefaultLayer.add(
          path.setLocationLayout(path.getLocationLayout().setLayerId(ModelConstants.DEFAULT_LAYER_ID))
      );
    }

    return model.setPoints(pointsAssignedToDefaultLayer)
        .setPaths(pathsAssignedToDefaultLayer)
        .setLocations(locationsAssignedToDefaultLayer);
  }

  private List<PointTO> convertPoints(V003PlantModelTO to,
                                      Map<String, ModelLayoutElement> modelLayoutElementMap) {
    return to.getPoints().stream()
        .map(point -> {
          Map<String, String> layoutProperties
              = toPropertiesMap(modelLayoutElementMap.get(point.getName()).getProperties());
          long positionX = layoutProperties.get(ElementPropKeys.POINT_POS_X) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.POINT_POS_X))
              : 0;
          long positionY = layoutProperties.get(ElementPropKeys.POINT_POS_Y) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.POINT_POS_Y))
              : 0;
          long labelOffsetX = layoutProperties.get(ElementPropKeys.POINT_LABEL_OFFSET_X) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.POINT_LABEL_OFFSET_X))
              : 0;
          long labelOffsetY = layoutProperties.get(ElementPropKeys.POINT_LABEL_OFFSET_Y) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.POINT_LABEL_OFFSET_Y))
              : 0;

          PointTO result = new PointTO();
          result.setName(point.getName())
              .setProperties(convertProperties(point.getProperties()));
          result.setxPosition(point.getxPosition())
              .setyPosition(point.getyPosition())
              .setzPosition(point.getzPosition())
              .setVehicleOrientationAngle(point.getVehicleOrientationAngle())
              .setType(point.getType())
              .setOutgoingPaths(convertOutgoingPaths(point))
              .setPointLayout(new PointTO.PointLayout()
                  .setxPosition(positionX)
                  .setyPosition(positionY)
                  .setxLabelOffset(labelOffsetX)
                  .setyLabelOffset(labelOffsetY));
          return result;
        })
        .collect(Collectors.toList());
  }

  private Map<String, String> toPropertiesMap(
      List<org.opentcs.util.persistence.v003.PropertyTO> properties) {
    Map<String, String> result = new HashMap<>();
    for (org.opentcs.util.persistence.v003.PropertyTO property : properties) {
      result.put(property.getName(), property.getValue());
    }
    return result;
  }

  private List<PointTO.OutgoingPath> convertOutgoingPaths(
      org.opentcs.util.persistence.v003.PointTO to) {
    return to.getOutgoingPaths().stream()
        .map(path -> new PointTO.OutgoingPath().setName(path.getName()))
        .collect(Collectors.toList());
  }

  private List<PathTO> convertPaths(V003PlantModelTO to,
                                    Map<String, ModelLayoutElement> modelLayoutElementMap) {
    return to.getPaths().stream()
        .map(path -> {
          Map<String, String> layoutProperties
              = toPropertiesMap(modelLayoutElementMap.get(path.getName()).getProperties());
          String connectionType = layoutProperties.getOrDefault(ElementPropKeys.PATH_CONN_TYPE,
                                                                "DIRECT");

          List<PathTO.ControlPoint> controlPoints = new ArrayList<>();
          String controlPointsString = layoutProperties.get(ElementPropKeys.PATH_CONTROL_POINTS);
          if (controlPointsString != null) {
            controlPoints = Arrays.asList(controlPointsString.split(";")).stream()
                .map(controlPointString -> {
                  String[] coordinateStrings = controlPointString.split(",");
                  return new PathTO.ControlPoint()
                      .setX(Long.parseLong(coordinateStrings[0]))
                      .setY(Long.parseLong(coordinateStrings[1]));
                })
                .collect(Collectors.toList());
          }

          PathTO result = new PathTO();
          result.setName(path.getName())
              .setProperties(convertProperties(path.getProperties()));
          result.setSourcePoint(path.getSourcePoint())
              .setDestinationPoint(path.getDestinationPoint())
              .setLength(path.getLength())
              .setMaxVelocity(path.getMaxVelocity())
              .setMaxReverseVelocity(path.getMaxReverseVelocity())
              .setLocked(path.isLocked())
              .setPathLayout(new PathTO.PathLayout()
                  .setConnectionType(connectionType)
                  .setControlPoints(controlPoints));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<VehicleTO> convertVehicles(V003PlantModelTO to,
                                          Map<String, ModelLayoutElement> modelLayoutElementMap) {
    return to.getVehicles().stream()
        .map(vehicle -> {
          Map<String, String> layoutProperties
              = toPropertiesMap(modelLayoutElementMap.get(vehicle.getName()).getProperties());
          String color = layoutProperties.get(ElementPropKeys.VEHICLE_ROUTE_COLOR) != null
              ? layoutProperties.get(ElementPropKeys.VEHICLE_ROUTE_COLOR)
              : Colors.encodeToHexRGB(Color.RED);

          VehicleTO result = new VehicleTO();
          result.setName(vehicle.getName())
              .setProperties(convertProperties(vehicle.getProperties()));
          result.setLength(vehicle.getLength())
              .setEnergyLevelCritical(vehicle.getEnergyLevelCritical())
              .setEnergyLevelGood(vehicle.getEnergyLevelGood())
              .setEnergyLevelFullyRecharged(vehicle.getEnergyLevelFullyRecharged())
              .setEnergyLevelSufficientlyRecharged(vehicle.getEnergyLevelSufficientlyRecharged())
              .setMaxVelocity(vehicle.getMaxVelocity())
              .setMaxReverseVelocity(vehicle.getMaxReverseVelocity())
              .setVehicleLayout(new VehicleTO.VehicleLayout()
                  .setColor(color));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<LocationTypeTO> convertLocationTypes(V003PlantModelTO to) {
    return to.getLocationTypes().stream()
        .map(locationType -> {
          String locationRepresentation = toPropertiesMap(locationType.getProperties())
              .getOrDefault(LOCTYPE_DEFAULT_REPRESENTATION, LocationRepresentation.NONE.name());

          LocationTypeTO result = new LocationTypeTO();
          result.setName(locationType.getName())
              .setProperties(convertProperties(locationType.getProperties()));
          result.setLocationNamePrefix(locationType.getLocationNamePrefix())
              .setAllowedOperations(convertAllowedOperations(locationType.getAllowedOperations()))
              .setLocationTypeLayout(new LocationTypeTO.LocationTypeLayout()
                  .setLocationRepresentation(locationRepresentation));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<AllowedOperationTO> convertAllowedOperations(
      List<org.opentcs.util.persistence.v003.AllowedOperationTO> tos) {
    return tos.stream()
        .map(allowedOperation -> {
          AllowedOperationTO result = new AllowedOperationTO();
          result.setName(allowedOperation.getName());
          result.setProperties(convertProperties(allowedOperation.getProperties()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<LocationTO> convertLocations(V003PlantModelTO to,
                                            Map<String, ModelLayoutElement> modelLayoutElementMap) {
    return to.getLocations().stream()
        .map(location -> {
          Map<String, String> layoutProperties
              = toPropertiesMap(modelLayoutElementMap.get(location.getName()).getProperties());
          long positionX = layoutProperties.get(ElementPropKeys.LOC_POS_X) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.LOC_POS_X))
              : 0;
          long positionY = layoutProperties.get(ElementPropKeys.LOC_POS_Y) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.LOC_POS_Y))
              : 0;
          long labelOffsetX = layoutProperties.get(ElementPropKeys.LOC_LABEL_OFFSET_X) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.LOC_LABEL_OFFSET_X))
              : 0;
          long labelOffsetY = layoutProperties.get(ElementPropKeys.LOC_LABEL_OFFSET_Y) != null
              ? Integer.parseInt(layoutProperties.get(ElementPropKeys.LOC_LABEL_OFFSET_Y))
              : 0;
          String locationRepresentation = toPropertiesMap(location.getProperties())
              .getOrDefault(LOC_DEFAULT_REPRESENTATION, LocationRepresentation.DEFAULT.name());

          LocationTO result = new LocationTO();
          result.setName(location.getName())
              .setProperties(convertProperties(location.getProperties()));
          result.setxPosition(location.getxPosition())
              .setyPosition(location.getyPosition())
              .setzPosition(location.getzPosition())
              .setType(location.getType())
              .setLinks(convertLinks(location))
              .setLocked(location.isLocked())
              .setLocationLayout(new LocationTO.LocationLayout()
                  .setxPosition(positionX)
                  .setyPosition(positionY)
                  .setxLabelOffset(labelOffsetX)
                  .setyLabelOffset(labelOffsetY)
                  .setLocationRepresentation(locationRepresentation));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<LocationTO.Link> convertLinks(org.opentcs.util.persistence.v003.LocationTO to) {
    return to.getLinks().stream()
        .map(link -> {
          return new LocationTO.Link()
              .setPoint(link.getPoint())
              .setAllowedOperations(convertAllowedOperations(link.getAllowedOperations()));
        })
        .collect(Collectors.toList());
  }

  private List<BlockTO> convertBlocks(V003PlantModelTO to,
                                      Map<String, ModelLayoutElement> modelLayoutElementMap) {
    return to.getBlocks().stream()
        .map(block -> {
          Map<String, String> layoutProperties
              = toPropertiesMap(modelLayoutElementMap.get(block.getName()).getProperties());
          String color = layoutProperties.get(ElementPropKeys.BLOCK_COLOR) != null
              ? layoutProperties.get(ElementPropKeys.BLOCK_COLOR)
              : Colors.encodeToHexRGB(Color.RED);

          BlockTO result = new BlockTO();
          result.setName(block.getName())
              .setProperties(convertProperties(block.getProperties()));
          result.setType(block.getType())
              .setMembers(convertMembers(block.getMembers()))
              .setBlockLayout(new BlockTO.BlockLayout()
                  .setColor(color));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<MemberTO> convertMembers(List<org.opentcs.util.persistence.v003.MemberTO> tos) {
    return tos.stream()
        .map(member -> {
          MemberTO result = new MemberTO();
          result.setName(member.getName())
              .setProperties(convertProperties(member.getProperties()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private VisualLayoutTO convertVisualLayout(V003PlantModelTO to) {
    VisualLayoutTO result = new VisualLayoutTO();
    result.setName(to.getVisualLayouts().get(0).getName())
        .setProperties(convertProperties(to.getVisualLayouts().get(0).getProperties()));
    result.setScaleX(to.getVisualLayouts().get(0).getScaleX())
        .setScaleY(to.getVisualLayouts().get(0).getScaleY())
        .setLayers(createDefaultLayer())
        .setLayerGroups(createDefaultLayerGroup());
    return result;
  }

  private List<VisualLayoutTO.Layer> createDefaultLayer() {
    return Arrays.asList(
        new VisualLayoutTO.Layer()
            .setId(ModelConstants.DEFAULT_LAYER_ID)
            .setOrdinal(ModelConstants.DEFAULT_LAYER_ORDINAL)
            .setVisible(Boolean.TRUE)
            .setName(ModelConstants.DEFAULT_LAYER_NAME)
            .setGroupId(ModelConstants.DEFAULT_LAYER_GROUP_ID)
    );
  }

  private List<VisualLayoutTO.LayerGroup> createDefaultLayerGroup() {
    return Arrays.asList(
        new VisualLayoutTO.LayerGroup()
            .setId(ModelConstants.DEFAULT_LAYER_GROUP_ID)
            .setVisible(Boolean.TRUE)
            .setName(ModelConstants.DEFAULT_LAYER_GROUP_NAME)
    );
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/AttributesComponent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import java.awt.Component;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JPanel;
import org.opentcs.guing.model.ComponentSelectionListener;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;

/**
 * A component for viewing and editing of properties. 
 * Shows a table with two columns. The left column contains the name of the property.
 * The right column contains the value of the property and can be clicked to edit the value.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class AttributesComponent
    extends JPanel
    implements ComponentSelectionListener {

  /**
   * The table with the properties.
   */
  private AttributesContent fPropertiesContent;
  private Component fPropertiesComponent;
  /**
   * The undo manager.
   */
  private final UndoRedoManager fUndoRedoManager;

  /**
   * Creates a new instance.
   *
   * @param undoManager The undo manager to use.
   */
  @Inject
  public AttributesComponent(UndoRedoManager undoManager) {
    fUndoRedoManager = requireNonNull(undoManager, "undoManager");
    initComponents();
  }

  @Override
  public void componentSelected(ModelComponent model) {
    setModel(model);
  }

  /**
   * Set the model component.
   *
   * @param model the model component to show properties for.
   */
  public void setModel(ModelComponent model) {
    fPropertiesContent.setModel(model);
    fPropertiesComponent.setVisible(!model.getProperties().isEmpty());

    setDescription();
  }

  /**
   * Resets the display when no model component should be shown.
   */
  public void reset() {
    if (fPropertiesContent != null) {
      fPropertiesContent.reset();
    }

    descriptionLabel.setText("");
  }

  /**
   * Set the text that describes the current model component.
   */
  protected void setDescription() {
    descriptionLabel.setText(fPropertiesContent.getDescription());
  }

  /**
   * Set the properties content.
   *
   * @param content the properties content.
   */
  public void setPropertiesContent(AttributesContent content) {
    fPropertiesContent = content;
    fPropertiesContent.setup(fUndoRedoManager);
    fPropertiesComponent = add(content.getComponent());
    fPropertiesComponent.setVisible(false);
  }

  public AttributesContent getPropertiesContent() {
    return fPropertiesContent;
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    descriptionLabel = new javax.swing.JLabel();

    setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));

    descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(descriptionLabel.getFont().getSize()+1f));
    descriptionLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    descriptionLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
    add(descriptionLabel);
  }// </editor-fold>//GEN-END:initComponents
  // Variables declaration - do not modify//GEN-BEGIN:variables
  protected javax.swing.JLabel descriptionLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/AbstractQuantity.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import org.opentcs.guing.model.ModelComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Base implementation for properties having a value and a unit.
 * (Examples: 1 s, 200 m, 30 m/s.)
 * Also specifies conversion relations (see {@link Relation}) between units that allow conversion
 * to other units.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 * @param <U> The enum type.
 */
public abstract class AbstractQuantity<U extends Enum<U>>
    extends AbstractProperty {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AbstractQuantity.class);
  /**
   * The unit's enum class;
   */
  private final Class<U> fUnitClass;
  /**
   * List of possible units.
   */
  private final List<U> fPossibleUnits;
  /**
   * List of relations between different units.
   */
  private final List<Relation<U>> fRelations;
  /**
   * Current unit.
   */
  private U fUnit;
  /**
   * Whether or not this property is an integer value.
   */
  private boolean fIsInteger;
  /**
   * Whether or not this property is unsigned.
   */
  private boolean fIsUnsigned;
  /**
   * A {@link ValidRangePair} indicating the range of the valid values
   * for this quantity.
   */
  protected ValidRangePair validRange = new ValidRangePair();

  /**
   * Creates a new instance.
   *
   * @param model The model component.
   * @param value The value.
   * @param unit The unit.
   * @param unitClass The unit class.
   * @param relations The relations.
   */
  public AbstractQuantity(ModelComponent model, double value, U unit, Class<U> unitClass,
                          List<Relation<U>> relations) {
    super(model);
    fUnit = requireNonNull(unit, "unit");
    fUnitClass = requireNonNull(unitClass, "unitClass");
    fPossibleUnits = Arrays.asList(unitClass.getEnumConstants());
    fRelations = requireNonNull(relations, "relations");
    fIsInteger = false;
    fIsUnsigned = false;
    initValidRange();
    setValue(value);
  }

  /**
   * Sets the new valid range.
   *
   * @param newRange The new {@link ValidRangePair}.
   */
  public void setValidRangePair(ValidRangePair newRange) {
    validRange = Objects.requireNonNull(newRange, "newRange is null");
  }

  /**
   * Returns the valid range for this quantity.
   *
   * @return The {@link ValidRangePair}.
   */
  public ValidRangePair getValidRange() {
    return validRange;
  }

  /**
   * Initializes the valid range of values.
   */
  protected abstract void initValidRange();

  /**
   * Sets the value of this property to be an integer or decimal number.
   *
   * @param isInteger Whether the value is an integer.
   */
  public void setInteger(boolean isInteger) {
    fIsInteger = isInteger;
  }

  /**
   * Returns true if the value of this property is an integer value.
   *
   * @return Whether the value is an integer.
   */
  public boolean isInteger() {
    return fIsInteger;
  }

  /**
   * Sets the value of this property to be unsigned or not.
   *
   * @param isUnsigned Whether the value is unsigned.
   */
  public void setUnsigned(boolean isUnsigned) {
    this.fIsUnsigned = isUnsigned;
  }

  /**
   * Indicates whether or not the value is unsigned or not.
   *
   * @return Whether the value is unsigned.
   */
  public boolean isUnsigned() {
    return fIsUnsigned;
  }

  @Override
  public Object getValue() {
    try {
      double value = Double.parseDouble(fValue.toString());

      if (isInteger()) {
        return (int) (value + 0.5);
      }
      else {
        return value;
      }
    }
    catch (NumberFormatException nfe) {
      LOG.info("Error parsing value", nfe);
      return fValue;
    }
  }

  /**
   * Returns the value of this property converted to the specified unit.
   *
   * @param unit The unit return.
   * @return The value by the given unit.
   */
  public double getValueByUnit(U unit) {
    try {
      @SuppressWarnings("unchecked")
      AbstractQuantity<U> property = (AbstractQuantity<U>) clone();
      // PercentProperty threw
      // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
      // this is a workaround 12.09.14
      double value;
      if (isInteger()) {
        value = ((Integer) getValue()).doubleValue();
      }
      else {
        value = (double) getValue();
      }
      property.setValueAndUnit(value, getUnit());
      property.convertTo(unit);
      if (isInteger()) {
        value = ((Integer) property.getValue()).doubleValue();
      }
      else {
        value = (double) property.getValue();
      }

      return value;
    }
    catch (IllegalArgumentException e) {
      LOG.error("Exception: ", e);
    }

    return Double.NaN;
  }

  /**
   * Converts the property to the new unit.
   *
   * @param unit The new unit to use.
   */
  public void convertTo(U unit) {
    if (!fPossibleUnits.contains(unit)) {
      return;
    }

    if (fUnit.equals(unit)) {
      return;
    }

    int indexUnitA = fPossibleUnits.indexOf(fUnit);
    int indexUnitB = fPossibleUnits.indexOf(unit);

    int lowerIndex;
    int upperIndex;
    if (indexUnitA < indexUnitB) {
      lowerIndex = indexUnitA;
      upperIndex = indexUnitB;
    }
    else {
      lowerIndex = indexUnitB;
      upperIndex = indexUnitA;
    }

    double relationValue = 1.0;

    for (int i = lowerIndex; i < upperIndex; i++) {
      U unitA = fPossibleUnits.get(i);
      U unitB = fPossibleUnits.get(i + 1);

      Relation<U> relation = findFittingRelation(unitA, unitB);
      relationValue *= relation.relationValue();
    }

    U lowerUnit = fPossibleUnits.get(lowerIndex);
    U upperUnit = fPossibleUnits.get(upperIndex);

    Relation<U> relation = new Relation<>(lowerUnit, upperUnit, relationValue);
    Relation.Operation operation = relation.getOperation(fUnit, unit);

    fUnit = unit;

    switch (operation) {
      case DIVISION:
        setValue((double) fValue / relation.relationValue());
        break;
      case MULTIPLICATION:
        setValue((double) fValue * relation.relationValue());
        break;
      default:
        throw new IllegalArgumentException("Unhandled operation: " + operation);
    }

  }

  /**
   * Returns the current unit for this property.
   *
   * @return The unit.
   */
  public U getUnit() {
    return fUnit;
  }

  /**
   * Checks if this property is applicable to the specified unit.
   *
   * @param unit The unit.
   * @return {@code true}, if the given unit is a valid/possible one, otherwise {@code false}.
   */
  public boolean isPossibleUnit(U unit) {
    return fPossibleUnits.contains(unit);
  }

  /**
   * Checks if the given string is a valid/possible unit.
   *
   * @param unitString The unit as a string.
   * @return {@code true}, if the given string is a valid/possible unit, otherwise {@code false}.
   */
  public boolean isPossibleUnit(String unitString) {
    for (U unit : fPossibleUnits) {
      if (Objects.equals(unitString, unit.toString())) {
        return true;
      }
    }
    return false;
  }

  /**
   * Set the value and unit for this property.
   * {@link IllegalArgumentException} is thrown if the unit is not applicable to this property.
   *
   * @param value The new value.
   * @param unit The new unit.
   * @throws IllegalArgumentException If the given unit is not usable.
   */
  public void setValueAndUnit(double value, U unit)
      throws IllegalArgumentException {
    if (!isPossibleUnit(unit)) {
      throw new IllegalArgumentException(String.format("'%s' is not a valid unit.", unit));
    }
    if (!Double.isNaN(value)) {
      if (fValue instanceof Double) {
        if ((double) fValue != value) {
          markChanged();
        }
      }
      else {
        markChanged();
      }
    }

    fUnit = unit;

    setValue(value);

    if (fIsUnsigned) {
      setValue(Math.abs(value));
    }
  }

  public void setValueAndUnit(double value, String unitString)
      throws IllegalArgumentException {
    requireNonNull(unitString);

    for (U unit : fUnitClass.getEnumConstants()) {
      if (unitString.equals(unit.toString())) {
        setValueAndUnit(value, unit);
        return;
      }
    }
    throw new IllegalArgumentException("Unknown unit \"" + unitString + "\"");
  }

  @Override
  public String toString() {
    if (fValue instanceof Integer) {
      return ((int) fValue) + " " + fUnit;
    }
    else if (fValue instanceof Double) {
      return fValue + " " + fUnit;
    }
    else {
      return fValue.toString();
    }
  }

  /**
   * Returns a list of possible units for this property.
   *
   * @return A list of possible units.
   */
  public List<U> getPossibleUnits() {
    return fPossibleUnits;
  }

  @Override
  public void copyFrom(Property property) {
    @SuppressWarnings("unchecked")
    AbstractQuantity<U> quantity = (AbstractQuantity<U>) property;

    try {
      if (quantity.getValue() instanceof Double) {
        setValueAndUnit((double) quantity.getValue(), quantity.getUnit());
      }
      else if (quantity.getValue() instanceof Integer) {
        setValueAndUnit(((Integer) quantity.getValue()).doubleValue(), quantity.getUnit());
      }
    }
    catch (IllegalArgumentException e) {
      LOG.error("Exception: ", e);
    }
  }

  /**
   * Finds the conversion relation that is applicable for both specified units.
   *
   * @return the conversion relation for the units.
   */
  private Relation<U> findFittingRelation(U unitFrom, U unitTo) {
    for (Relation<U> relation : fRelations) {
      if (relation.fits(unitFrom, unitTo)) {
        return relation;
      }
    }

    return null;
  }

  public class ValidRangePair {

    private double min = Double.NEGATIVE_INFINITY;
    private double max = Double.MAX_VALUE;

    public ValidRangePair() {
    }

    public ValidRangePair(double min, double max) {
      this.min = min;
      this.max = max;
    }

    /**
     * Returns whether the given value is in the valid range.
     *
     * @param value The value to test.
     * @return <code>true</code> if the value is in range, <code>false</code>
     * otherwise.
     */
    public boolean isValueValid(double value) {
      return value >= min && value <= max;
    }

    public double getMin() {
      return min;
    }

    public ValidRangePair setMin(double min) {
      this.min = min;
      return this;
    }

    public double getMax() {
      return max;
    }

    public ValidRangePair setMax(double max) {
      this.max = max;
      return this;
    }
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v002/VisualLayoutTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v002;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "id", "scaleX", "scaleY", "colors", "shapeLayoutElements",
                      "modelLayoutElements", "viewBookmarks", "properties"})
public class VisualLayoutTO
    extends PlantModelElementTO {

  private Float scaleX = 0.0F;
  private Float scaleY = 0.0F;
  private List<Color> colors = new ArrayList<>();
  private List<ShapeLayoutElement> shapeLayoutElements = new ArrayList<>();
  private List<ModelLayoutElement> modelLayoutElements = new ArrayList<>();
  private List<ViewBookmark> viewBookmarks = new ArrayList<>();

  @XmlAttribute(required = true)
  public Float getScaleX() {
    return scaleX;
  }

  public VisualLayoutTO setScaleX(@Nonnull Float scaleX) {
    requireNonNull(scaleX, "scaleX");
    this.scaleX = scaleX;
    return this;
  }

  @XmlAttribute(required = true)
  public Float getScaleY() {
    return scaleY;
  }

  public VisualLayoutTO setScaleY(@Nonnull Float scaleY) {
    requireNonNull(scaleY, "scaleY");
    this.scaleY = scaleY;
    return this;
  }

  @XmlElement(name = "color")
  public List<Color> getColors() {
    return colors;
  }

  public VisualLayoutTO setColors(@Nonnull List<Color> colors) {
    requireNonNull(colors, "colors");
    this.colors = colors;
    return this;
  }

  @XmlElement(name = "shapeLayoutElement")
  public List<ShapeLayoutElement> getShapeLayoutElements() {
    return shapeLayoutElements;
  }

  public VisualLayoutTO setShapeLayoutElements(@Nonnull List<ShapeLayoutElement> shapeLayoutElements) {
    requireNonNull(shapeLayoutElements, "shapeLayoutElements");
    this.shapeLayoutElements = shapeLayoutElements;
    return this;
  }

  @XmlElement(name = "modelLayoutElement")
  public List<ModelLayoutElement> getModelLayoutElements() {
    return modelLayoutElements;
  }

  public VisualLayoutTO setModelLayoutElements(@Nonnull List<ModelLayoutElement> modelLayoutElements) {
    requireNonNull(modelLayoutElements, "modelLayoutElements");
    this.modelLayoutElements = modelLayoutElements;
    return this;
  }

  @XmlElement(name = "viewBookmark")
  public List<ViewBookmark> getViewBookmarks() {
    return viewBookmarks;
  }

  public VisualLayoutTO setViewBookmarks(@Nonnull List<ViewBookmark> viewBookmarks) {
    requireNonNull(viewBookmarks, "viewBookmarks");
    this.viewBookmarks = viewBookmarks;
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"name", "redValue", "greenValue", "blueValue"})
  public static class Color {

    private String name = "";
    private Long redValue = 0L;
    private Long greenValue = 0L;
    private Long blueValue = 0L;

    @XmlAttribute(required = true)
    public String getName() {
      return name;
    }

    public Color setName(@Nonnull String name) {
      requireNonNull(name, "name");
      this.name = name;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getRedValue() {
      return redValue;
    }

    public Color setRedValue(@Nonnull Long redValue) {
      requireNonNull(redValue, "redValue");
      this.redValue = redValue;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getGreenValue() {
      return greenValue;
    }

    public Color setGreenValue(@Nonnull Long greenValue) {
      requireNonNull(greenValue, "greenValue");
      this.greenValue = greenValue;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getBlueValue() {
      return blueValue;
    }

    public Color setBlueValue(@Nonnull Long blueValue) {
      requireNonNull(blueValue, "blueValue");
      this.blueValue = blueValue;
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"layer", "properties"})
  public static class ShapeLayoutElement {

    private Long layer = 0L;
    private List<PropertyTO> properties = new ArrayList<>();

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getLayer() {
      return layer;
    }

    public ShapeLayoutElement setLayer(@Nonnull Long layer) {
      requireNonNull(layer, "layer");
      this.layer = layer;
      return this;
    }

    @XmlElement(name = "property")
    public List<PropertyTO> getProperties() {
      return properties;
    }

    public ShapeLayoutElement setProperties(@Nonnull List<PropertyTO> properties) {
      requireNonNull(properties, "properties");
      this.properties = properties;
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"visualizedObjectName", "layer", "properties"})
  public static class ModelLayoutElement {

    private String visualizedObjectName = "";
    private Long layer = 0L;
    private List<PropertyTO> properties = new ArrayList<>();

    @XmlAttribute(required = true)
    public String getVisualizedObjectName() {
      return visualizedObjectName;
    }

    public ModelLayoutElement setVisualizedObjectName(@Nonnull String visualizedObjectName) {
      requireNonNull(visualizedObjectName, "visualizedObjectName");
      this.visualizedObjectName = visualizedObjectName;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getLayer() {
      return layer;
    }

    public ModelLayoutElement setLayer(@Nonnull Long layer) {
      requireNonNull(layer, "layer");
      this.layer = layer;
      return this;
    }

    @XmlElement(name = "property")
    public List<PropertyTO> getProperties() {
      return properties;
    }

    public ModelLayoutElement setProperties(@Nonnull List<PropertyTO> properties) {
      requireNonNull(properties, "properties");
      this.properties = properties;
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"label", "centerX", "centerY", "viewScaleX", "viewScaleY", "viewRotation"})
  public static class ViewBookmark {

    private String label = "";
    private Integer centerX = 0;
    private Integer centerY = 0;
    private Float viewScaleX = 0.0F;
    private Float viewScaleY = 0.0F;
    private Integer viewRotation = 0;

    @XmlAttribute(required = true)
    public String getLabel() {
      return label;
    }

    public ViewBookmark setLabel(@Nonnull String label) {
      requireNonNull(label, "label");
      this.label = label;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "int")
    public Integer getCenterX() {
      return centerX;
    }

    public ViewBookmark setCenterX(@Nonnull Integer centerX) {
      requireNonNull(centerX, "centerX");
      this.centerX = centerX;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "int")
    public Integer getCenterY() {
      return centerY;
    }

    public ViewBookmark setCenterY(@Nonnull Integer centerY) {
      requireNonNull(centerY, "centerY");
      this.centerY = centerY;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "float")
    public Float getViewScaleX() {
      return viewScaleX;
    }

    public ViewBookmark setViewScaleX(@Nonnull Float viewScaleX) {
      requireNonNull(viewScaleX, "viewScaleX");
      this.viewScaleX = viewScaleX;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "float")
    public Float getViewScaleY() {
      return viewScaleY;
    }

    public ViewBookmark setViewScaleY(@Nonnull Float viewScaleY) {
      requireNonNull(viewScaleY, "viewScaleY");
      this.viewScaleY = viewScaleY;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "int")
    public Integer getViewRotation() {
      return viewRotation;
    }

    public ViewBookmark setViewRotation(@Nonnull Integer viewRotation) {
      requireNonNull(viewRotation, "viewRotation");
      this.viewRotation = viewRotation;
      return this;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/LayoutModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.HashMap;
import java.util.ResourceBundle;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.LayerGroupsProperty;
import org.opentcs.guing.components.properties.type.LayerWrappersProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.model.CompositeModelComponent;

/**
 * Basic implementation of a layout.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class LayoutModel
    extends CompositeModelComponent {

  public static final String SCALE_X = "scaleX";
  public static final String SCALE_Y = "scaleY";
  public static final String LAYERS_WRAPPERS = "layerWrappers";
  public static final String LAYER_GROUPS = "layerGroups";
  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);

  /**
   * Creates a new instance.
   */
  public LayoutModel() {
    super(ResourceBundle.getBundle(BUNDLE_PATH).getString("layoutModel.treeViewName"));
    createProperties();
  }

  @Override // AbstractModelComponent
  public String getDescription() {
    return bundle.getString("layoutModel.description");
  }

  public LengthProperty getPropertyScaleX() {
    return (LengthProperty) getProperty(SCALE_X);
  }

  public LengthProperty getPropertyScaleY() {
    return (LengthProperty) getProperty(SCALE_Y);
  }

  public KeyValueSetProperty getPropertyMiscellaneous() {
    return (KeyValueSetProperty) getProperty(MISCELLANEOUS);
  }

  public LayerWrappersProperty getPropertyLayerWrappers() {
    return (LayerWrappersProperty) getProperty(LAYERS_WRAPPERS);
  }

  public LayerGroupsProperty getPropertyLayerGroups() {
    return (LayerGroupsProperty) getProperty(LAYER_GROUPS);
  }

  private void createProperties() {
    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("layoutModel.property_name.description"));
    pName.setHelptext(bundle.getString("layoutModel.property_name.helptext"));
    setProperty(NAME, pName);

    LengthProperty pScaleX = new LengthProperty(this);
    pScaleX.setDescription(bundle.getString("layoutModel.property_scaleX.description"));
    pScaleX.setHelptext(bundle.getString("layoutModel.property_scaleX.helptext"));
    setProperty(SCALE_X, pScaleX);

    LengthProperty pScaleY = new LengthProperty(this);
    pScaleY.setDescription(bundle.getString("layoutModel.property_scaleY.description"));
    pScaleY.setHelptext(bundle.getString("layoutModel.property_scaleY.helptext"));
    setProperty(SCALE_Y, pScaleY);

    KeyValueSetProperty pMiscellaneous = new KeyValueSetProperty(this);
    pMiscellaneous.setDescription(bundle.getString("layoutModel.property_miscellaneous.description"));
    pMiscellaneous.setHelptext(bundle.getString("layoutModel.property_miscellaneous.helptext"));
    pMiscellaneous.setOperatingEditable(true);
    setProperty(MISCELLANEOUS, pMiscellaneous);

    LayerWrappersProperty pLayerWrappers = new LayerWrappersProperty(this, new HashMap<>());
    pLayerWrappers.setDescription(bundle.getString("layoutModel.property_layerWrappers.description"));
    pLayerWrappers.setHelptext(bundle.getString("layoutModel.property_layerWrappers.helptext"));
    pLayerWrappers.setModellingEditable(false);
    setProperty(LAYERS_WRAPPERS, pLayerWrappers);

    LayerGroupsProperty pLayerGroups = new LayerGroupsProperty(this, new HashMap<>());
    pLayerGroups.setDescription(bundle.getString("layoutModel.property_layerGroups.description"));
    pLayerGroups.setHelptext(bundle.getString("layoutModel.property_layerGroups.helptext"));
    pLayerGroups.setModellingEditable(false);
    setProperty(LAYER_GROUPS, pLayerGroups);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/VehicleControllerFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;

/**
 * A factory for <code>VehicleManager</code> instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleControllerFactory {

  /**
   * Creates a new vehicle controller for the given vehicle and communication adapter.
   *
   * @param vehicle The vehicle.
   * @param commAdapter The communication adapter.
   * @return A new vehicle controller.
   */
  DefaultVehicleController createVehicleController(Vehicle vehicle, VehicleCommAdapter commAdapter);
}


<|start_filename|>openTCS-Kernel/src/guiceConfig/java/org/opentcs/kernel/DefaultKernelInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.multibindings.MapBinder;
import java.io.File;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import javax.inject.Singleton;
import org.opentcs.access.Kernel;
import org.opentcs.access.LocalKernel;
import org.opentcs.access.SslParameterSet;
import org.opentcs.common.LoggingScheduledThreadPoolExecutor;
import org.opentcs.components.kernel.ObjectNameProvider;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.InternalPeripheralJobService;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.components.kernel.services.InternalQueryService;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.components.kernel.services.InternalVehicleService;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.components.kernel.services.PeripheralJobService;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.components.kernel.services.QueryService;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.components.kernel.services.SchedulerService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.components.kernel.services.VehicleService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.ApplicationHome;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.opentcs.drivers.peripherals.PeripheralControllerPool;
import org.opentcs.drivers.vehicle.VehicleControllerPool;
import org.opentcs.kernel.extensions.controlcenter.vehicles.AttachmentManager;
import org.opentcs.kernel.extensions.controlcenter.vehicles.VehicleEntryPool;
import org.opentcs.kernel.peripherals.DefaultPeripheralControllerPool;
import org.opentcs.kernel.peripherals.LocalPeripheralControllerPool;
import org.opentcs.kernel.peripherals.PeripheralAttachmentManager;
import org.opentcs.kernel.peripherals.PeripheralCommAdapterRegistry;
import org.opentcs.kernel.peripherals.PeripheralControllerFactory;
import org.opentcs.kernel.peripherals.PeripheralEntryPool;
import org.opentcs.kernel.persistence.ModelPersister;
import org.opentcs.kernel.persistence.XMLFileModelPersister;
import org.opentcs.kernel.services.StandardDispatcherService;
import org.opentcs.kernel.services.StandardNotificationService;
import org.opentcs.kernel.services.StandardPeripheralDispatcherService;
import org.opentcs.kernel.services.StandardPeripheralJobService;
import org.opentcs.kernel.services.StandardPeripheralService;
import org.opentcs.kernel.services.StandardPlantModelService;
import org.opentcs.kernel.services.StandardQueryService;
import org.opentcs.kernel.services.StandardRouterService;
import org.opentcs.kernel.services.StandardSchedulerService;
import org.opentcs.kernel.services.StandardTCSObjectService;
import org.opentcs.kernel.services.StandardTransportOrderService;
import org.opentcs.kernel.services.StandardVehicleService;
import org.opentcs.kernel.vehicles.DefaultVehicleControllerPool;
import org.opentcs.kernel.vehicles.LocalVehicleControllerPool;
import org.opentcs.kernel.vehicles.VehicleCommAdapterRegistry;
import org.opentcs.kernel.vehicles.VehicleControllerComponentsFactory;
import org.opentcs.kernel.vehicles.VehicleControllerFactory;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.NotificationBuffer;
import org.opentcs.kernel.workingset.PeripheralJobPool;
import org.opentcs.kernel.workingset.PrefixedUlidObjectNameProvider;
import org.opentcs.kernel.workingset.TCSObjectPool;
import org.opentcs.kernel.workingset.TransportOrderPool;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.SimpleEventBus;
import org.opentcs.util.logging.UncaughtExceptionLogger;

/**
 * A Guice module for the openTCS kernel application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultKernelInjectionModule
    extends KernelInjectionModule {

  @Override
  protected void configure() {
    configureEventHub();
    configureKernelExecutor();

    // Ensure that the application's home directory can be used everywhere.
    File applicationHome = new File(System.getProperty("opentcs.home", "."));
    bind(File.class)
        .annotatedWith(ApplicationHome.class)
        .toInstance(applicationHome);

    // A single global synchronization object for the kernel.
    bind(Object.class)
        .annotatedWith(GlobalSyncObject.class)
        .to(Object.class)
        .in(Singleton.class);

    // The kernel's data pool structures.
    bind(TCSObjectPool.class).in(Singleton.class);
    bind(Model.class).in(Singleton.class);
    bind(TransportOrderPool.class).in(Singleton.class);
    bind(PeripheralJobPool.class).in(Singleton.class);
    bind(NotificationBuffer.class).in(Singleton.class);

    bind(ObjectNameProvider.class)
        .to(PrefixedUlidObjectNameProvider.class)
        .in(Singleton.class);

    configurePersistence();

    bind(VehicleCommAdapterRegistry.class)
        .in(Singleton.class);

    configureVehicleControllers();

    bind(AttachmentManager.class)
        .in(Singleton.class);
    bind(VehicleEntryPool.class)
        .in(Singleton.class);

    configurePeripheralControllers();

    bind(PeripheralCommAdapterRegistry.class)
        .in(Singleton.class);
    bind(PeripheralAttachmentManager.class)
        .in(Singleton.class);
    bind(PeripheralEntryPool.class)
        .in(Singleton.class);

    bind(StandardKernel.class)
        .in(Singleton.class);
    bind(LocalKernel.class)
        .to(StandardKernel.class);

    configureKernelStatesDependencies();
    configureKernelStarterDependencies();
    configureSslParameters();
    configureKernelServicesDependencies();

    // Ensure all of these binders are initialized.
    extensionsBinderAllModes();
    extensionsBinderModelling();
    extensionsBinderOperating();
    vehicleCommAdaptersBinder();
    peripheralCommAdaptersBinder();
  }

  private void configureKernelServicesDependencies() {
    bind(StandardPlantModelService.class).in(Singleton.class);
    bind(PlantModelService.class).to(StandardPlantModelService.class);
    bind(InternalPlantModelService.class).to(StandardPlantModelService.class);

    bind(StandardTransportOrderService.class).in(Singleton.class);
    bind(TransportOrderService.class).to(StandardTransportOrderService.class);
    bind(InternalTransportOrderService.class).to(StandardTransportOrderService.class);

    bind(StandardVehicleService.class).in(Singleton.class);
    bind(VehicleService.class).to(StandardVehicleService.class);
    bind(InternalVehicleService.class).to(StandardVehicleService.class);

    bind(StandardTCSObjectService.class).in(Singleton.class);
    bind(TCSObjectService.class).to(StandardTCSObjectService.class);

    bind(StandardNotificationService.class).in(Singleton.class);
    bind(NotificationService.class).to(StandardNotificationService.class);

    bind(StandardRouterService.class).in(Singleton.class);
    bind(RouterService.class).to(StandardRouterService.class);

    bind(StandardDispatcherService.class).in(Singleton.class);
    bind(DispatcherService.class).to(StandardDispatcherService.class);

    bind(StandardSchedulerService.class).in(Singleton.class);
    bind(SchedulerService.class).to(StandardSchedulerService.class);

    bind(StandardQueryService.class).in(Singleton.class);
    bind(QueryService.class).to(StandardQueryService.class);
    bind(InternalQueryService.class).to(StandardQueryService.class);

    bind(StandardPeripheralService.class).in(Singleton.class);
    bind(PeripheralService.class).to(StandardPeripheralService.class);
    bind(InternalPeripheralService.class).to(StandardPeripheralService.class);

    bind(StandardPeripheralJobService.class).in(Singleton.class);
    bind(PeripheralJobService.class).to(StandardPeripheralJobService.class);
    bind(InternalPeripheralJobService.class).to(StandardPeripheralJobService.class);

    bind(StandardPeripheralDispatcherService.class).in(Singleton.class);
    bind(PeripheralDispatcherService.class).to(StandardPeripheralDispatcherService.class);
  }

  private void configureVehicleControllers() {
    install(new FactoryModuleBuilder().build(VehicleControllerFactory.class));
    install(new FactoryModuleBuilder().build(VehicleControllerComponentsFactory.class));

    bind(DefaultVehicleControllerPool.class)
        .in(Singleton.class);
    bind(VehicleControllerPool.class)
        .to(DefaultVehicleControllerPool.class);
    bind(LocalVehicleControllerPool.class)
        .to(DefaultVehicleControllerPool.class);
  }

  private void configurePeripheralControllers() {
    install(new FactoryModuleBuilder().build(PeripheralControllerFactory.class));

    bind(DefaultPeripheralControllerPool.class)
        .in(Singleton.class);
    bind(PeripheralControllerPool.class)
        .to(DefaultPeripheralControllerPool.class);
    bind(LocalPeripheralControllerPool.class)
        .to(DefaultPeripheralControllerPool.class);
  }

  private void configurePersistence() {
    bind(ModelPersister.class).to(XMLFileModelPersister.class);
  }

  private void configureEventHub() {
    EventBus newEventBus = new SimpleEventBus();
    bind(EventHandler.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(newEventBus);
    bind(org.opentcs.util.event.EventSource.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(newEventBus);
    bind(EventBus.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(newEventBus);
  }

  private void configureKernelStatesDependencies() {
    // A map for KernelState instances to be provided at runtime.
    MapBinder<Kernel.State, KernelState> stateMapBinder
        = MapBinder.newMapBinder(binder(), Kernel.State.class, KernelState.class);
    stateMapBinder.addBinding(Kernel.State.SHUTDOWN).to(KernelStateShutdown.class);
    stateMapBinder.addBinding(Kernel.State.MODELLING).to(KernelStateModelling.class);
    stateMapBinder.addBinding(Kernel.State.OPERATING).to(KernelStateOperating.class);

    bind(OrderPoolConfiguration.class)
        .toInstance(getConfigBindingProvider().get(OrderPoolConfiguration.PREFIX,
                                                   OrderPoolConfiguration.class));

    transportOrderCleanupApprovalBinder();
    orderSequenceCleanupApprovalBinder();
  }

  private void configureKernelStarterDependencies() {
    bind(KernelApplicationConfiguration.class)
        .toInstance(getConfigBindingProvider().get(KernelApplicationConfiguration.PREFIX,
                                                   KernelApplicationConfiguration.class));
  }

  private void configureSslParameters() {
    SslConfiguration configuration
        = getConfigBindingProvider().get(SslConfiguration.PREFIX,
                                         SslConfiguration.class);
    SslParameterSet sslParamSet = new SslParameterSet(SslParameterSet.DEFAULT_KEYSTORE_TYPE,
                                                      new File(configuration.keystoreFile()),
                                                      configuration.keystorePassword(),
                                                      new File(configuration.truststoreFile()),
                                                      configuration.truststorePassword());
    bind(SslParameterSet.class).toInstance(sslParamSet);
  }

  private void configureKernelExecutor() {
    ScheduledExecutorService executor
        = new LoggingScheduledThreadPoolExecutor(
            1,
            runnable -> {
              Thread thread = new Thread(runnable, "kernelExecutor");
              thread.setUncaughtExceptionHandler(new UncaughtExceptionLogger(false));
              return thread;
            }
        );
    bind(ScheduledExecutorService.class)
        .annotatedWith(KernelExecutor.class)
        .toInstance(executor);
    bind(ExecutorService.class)
        .annotatedWith(KernelExecutor.class)
        .toInstance(executor);
    bind(Executor.class)
        .annotatedWith(KernelExecutor.class)
        .toInstance(executor);
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/test/java/org/opentcs/kernel/extensions/servicewebapi/v1/status/StatusEventDispatcherTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.servicewebapi.v1.status;

import java.util.ArrayList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import org.junit.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.kernel.extensions.servicewebapi.ServiceWebApiConfiguration;
import org.opentcs.kernel.extensions.servicewebapi.v1.status.binding.StatusMessageList;
import org.opentcs.util.event.EventSource;
import org.opentcs.util.event.SimpleEventBus;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatusEventDispatcherTest {

  private ServiceWebApiConfiguration configuration;

  private EventSource eventSource;

  private StatusEventDispatcher statusEventDispatcher;

  @Before
  public void setUp() {
    configuration = mock(ServiceWebApiConfiguration.class);
    eventSource = new SimpleEventBus();
    statusEventDispatcher = new StatusEventDispatcher(configuration, eventSource);
  }

  @Test
  public void returnEmptyListIfThereWereNoEvents() {
    statusEventDispatcher.initialize();

    StatusMessageList list = statusEventDispatcher.fetchEvents(0, Long.MAX_VALUE, 1);
    assertThat(list.getStatusMessages(), is(empty()));
  }

  @Test
  public void respectConfiguredCapacity() {
    final int capacity = 10;
    final int eventCount = capacity * 2;
    when(configuration.statusEventsCapacity()).thenReturn(capacity);
    statusEventDispatcher.initialize();

    TransportOrder order = new TransportOrder("SomeOrder", new ArrayList<>());
    for (int i = 0; i < eventCount; i++) {
      statusEventDispatcher.onEvent(
          new TCSObjectEvent(order, order, TCSObjectEvent.Type.OBJECT_MODIFIED)
      );
    }

    StatusMessageList list = statusEventDispatcher.fetchEvents(0, Long.MAX_VALUE, 1);
    assertThat(list.getStatusMessages().size(), is(capacity));
    assertThat(list.getStatusMessages().get(capacity - 1).getSequenceNumber(),
               is((long) eventCount - 1));
  }

  @Test
  public void keepAllEventsIfLessThanCapacity() {
    final int capacity = 10;
    final int eventCount = capacity / 2;
    when(configuration.statusEventsCapacity()).thenReturn(capacity);
    statusEventDispatcher.initialize();

    TransportOrder order = new TransportOrder("SomeOrder", new ArrayList<>());
    for (int i = 0; i < 5; i++) {
      statusEventDispatcher.onEvent(
          new TCSObjectEvent(order, order, TCSObjectEvent.Type.OBJECT_MODIFIED)
      );
    }

    StatusMessageList list = statusEventDispatcher.fetchEvents(0, Long.MAX_VALUE, 1);
    assertThat(list.getStatusMessages().size(), is(eventCount));
    assertThat(list.getStatusMessages().get(eventCount - 1).getSequenceNumber(),
               is((long) eventCount - 1));
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/LocationFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import com.google.inject.assistedinject.Assisted;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ImageObserver;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.draw.AttributeKeys;
import org.jhotdraw.draw.ConnectionFigure;
import org.jhotdraw.draw.connector.ChopEllipseConnector;
import org.jhotdraw.draw.connector.Connector;
import org.jhotdraw.geom.Geom;
import org.opentcs.components.plantoverview.LocationTheme;
import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.components.drawing.DrawingOptions;
import org.opentcs.guing.components.drawing.Strokes;
import org.opentcs.guing.components.drawing.ZoomPoint;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.type.SymbolProperty;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * A figure for locations.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class LocationFigure
    extends TCSFigure
    implements ImageObserver {

  /**
   * The fill color for locked locations.
   */
  private static final Color LOCKED_COLOR = new Color(255, 50, 50);
  /**
   * The image representing the location.
   */
  private transient Image fImage;
  private int fWidth;
  private int fHeight;
  private final LocationTheme locationTheme;
  private final DrawingOptions drawingOptions;

  /**
   * Creates a new instance.
   *
   * @param locationTheme The location theme to be used.
   * @param model The model corresponding to this graphical object.
   * @param drawingOptions The drawing options.
   */
  @Inject
  public LocationFigure(LocationTheme locationTheme,
                        @Assisted LocationModel model,
                        DrawingOptions drawingOptions) {
    super(model);
    this.locationTheme = requireNonNull(locationTheme, "locationTheme");
    this.drawingOptions = requireNonNull(drawingOptions, "drawingOptions");

    fWidth = 30;
    fHeight = 30;
    fDisplayBox = new Rectangle(fWidth, fHeight);
    fZoomPoint = new ZoomPoint(0.5 * fWidth, 0.5 * fHeight);
  }

  @Override
  public LocationModel getModel() {
    return (LocationModel) get(FigureConstants.MODEL);
  }

  public Point center() {
    return Geom.center(fDisplayBox);
  }

  @Override // Figure
  public Rectangle2D.Double getBounds() {
    Rectangle2D r2 = fDisplayBox.getBounds2D();
    Rectangle2D.Double r2d = new Rectangle2D.Double();
    r2d.setRect(r2);

    return r2d;
  }

  @Override  // Figure
  public Object getTransformRestoreData() {
    return fDisplayBox.clone();
  }

  @Override  // Figure
  public void restoreTransformTo(Object restoreData) {
    Rectangle r = (Rectangle) restoreData;
    fDisplayBox.x = r.x;
    fDisplayBox.y = r.y;
    fDisplayBox.width = r.width;
    fDisplayBox.height = r.height;
    fZoomPoint.setX(r.x + 0.5 * r.width);
    fZoomPoint.setY(r.y + 0.5 * r.height);
  }

  @Override  // Figure
  public void transform(AffineTransform tx) {
    Point2D center = getZoomPoint().getPixelLocationExactly();
    setBounds((Point2D.Double) tx.transform(center, center), null);
  }

  @Override  // AbstractFigure
  public void setBounds(Point2D.Double anchor, Point2D.Double lead) {
    fZoomPoint.setX(anchor.x);
    fZoomPoint.setY(anchor.y);
    fDisplayBox.x = (int) (anchor.x - 0.5 * fDisplayBox.width);
    fDisplayBox.y = (int) (anchor.y - 0.5 * fDisplayBox.height);
  }

  @Override // AbstractFigure
  public Connector findConnector(Point2D.Double p, ConnectionFigure prototype) {
    return new ChopEllipseConnector(this);
  }

  @Override // AbstractFigure
  public Connector findCompatibleConnector(Connector c, boolean isStartConnector) {
    return new ChopEllipseConnector(this);
  }

  @Override
  public int getLayer() {
    return getModel().getPropertyLayerWrapper().getValue().getLayer().getOrdinal();
  }

  @Override
  public boolean isVisible() {
    return super.isVisible()
        && getModel().getPropertyLayerWrapper().getValue().getLayer().isVisible()
        && getModel().getPropertyLayerWrapper().getValue().getLayerGroup().isVisible();
  }

  @Override
  protected void drawFigure(Graphics2D g) {
    if (drawingOptions.isBlocksVisible()) {
      drawBlockDecoration(g);
    }
    drawRouteDecoration(g);

    super.drawFigure(g);
  }

  private void drawRouteDecoration(Graphics2D g) {
    for (VehicleModel vehicleModel : getModel().getVehicleModels()) {
      Stroke stroke = Strokes.PATH_ON_ROUTE;
      Color color = transparentColor(vehicleModel.getDriveOrderColor(), 192);
      if (vehicleModel.getDriveOrderState() == TransportOrder.State.WITHDRAWN) {
        stroke = Strokes.PATH_ON_WITHDRAWN_ROUTE;
        color = Color.GRAY;
      }

      drawDecoration(g, stroke, color);
    }
  }

  private void drawBlockDecoration(Graphics2D g) {
    for (BlockModel blockModel : getModel().getBlockModels()) {
      drawDecoration(g, Strokes.BLOCK_ELEMENT, transparentColor(blockModel.getColor(), 192));
    }
  }

  private Color transparentColor(Color color, int alpha) {
    return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
  }

  private void drawDecoration(Graphics2D g, Stroke stroke, Color color) {
    g.setStroke(stroke);
    g.setColor(color);
    g.draw(this.getDrawingArea());
  }

  @Override  // AbstractAttributedFigure
  protected void drawFill(Graphics2D g) {
    int dx;
    int dy;
    Rectangle r = displayBox();
    g.fillRect(r.x, r.y, r.width, r.height);

    if (fImage != null) {
      dx = (r.width - fImage.getWidth(this)) / 2;
      dy = (r.height - fImage.getHeight(this)) / 2;
      g.drawImage(fImage, r.x + dx, r.y + dy, this);
    }
  }

  @Override  // AbstractAttributedFigure
  protected void drawStroke(Graphics2D g) {
    Rectangle r = displayBox();
    g.drawRect(r.x, r.y, r.width - 1, r.height - 1);
  }

  @Override
  public LocationFigure clone() {
    LocationFigure thatFigure = (LocationFigure) super.clone();
    thatFigure.setZoomPoint(new ZoomPoint(fZoomPoint.getX(), fZoomPoint.getY()));

    return thatFigure;
  }

  @Override  // ImageObserver
  public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
    if ((infoflags & (FRAMEBITS | ALLBITS)) != 0) {
      invalidate();
    }

    return (infoflags & (ALLBITS | ABORT)) == 0;
  }

  public void propertiesChanged(AttributesChangeEvent e) {
    handleLocationTypeChanged();
    handleLocationLockChanged();
  }

  private void handleLocationTypeChanged() {
    LocationTypeModel locationType = getModel().getLocationType();

    if (locationType == null) {
      return;
    }
    if (getModel().getLocation() != null && locationType.getLocationType() != null) {
      fImage = locationTheme.getImageFor(getModel().getLocation(), locationType.getLocationType());
    }
    else {
      SymbolProperty pSymbol = getModel().getPropertyDefaultRepresentation();
      LocationRepresentation locationRepresentation = pSymbol.getLocationRepresentation();
      if (locationRepresentation == null
          || locationRepresentation == LocationRepresentation.DEFAULT) {
        pSymbol = locationType.getPropertyDefaultRepresentation();
        locationRepresentation = pSymbol.getLocationRepresentation();
        fImage = locationTheme.getImageFor(locationRepresentation);
      }
      else {
        fImage = locationTheme.getImageFor(locationRepresentation);
      }
    }
    fWidth = Math.max(fImage.getWidth(this) + 10, 30);
    fHeight = Math.max(fImage.getHeight(this) + 10, 30);
    fDisplayBox.setSize(fWidth, fHeight);
  }

  private void handleLocationLockChanged() {
    set(AttributeKeys.FILL_COLOR,
        (Boolean) getModel().getPropertyLocked().getValue() ? LOCKED_COLOR : Color.WHITE);
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/ResourceProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property that holds a list of sets of {@link TCSResourceReference}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ResourceProperty
    extends AbstractComplexProperty {

  /**
   * A list of of sets {@link TCSResourceReference}s.
   */
  private List<Set<TCSResourceReference<?>>> items = new ArrayList<>();

  /**
   * Creates a new ResourceProperty instance.
   *
   * @param model The model component this property belongs to.
   */
  public ResourceProperty(ModelComponent model) {
    super(model);
  }

  @Override
  public Object getComparableValue() {
    return items.stream()
        .flatMap(set -> set.stream())
        .map(r -> r.getName())
        .collect(Collectors.joining());
  }

  /**
   * Returns a list of all items of this property.
   *
   * @return a list of all items of this property.
   */
  public List<Set<TCSResourceReference<?>>> getItems() {
    return items;
  }

  /**
   * Sets the list.
   *
   * @param items the list of items for this property.
   */
  public void setItems(List<Set<TCSResourceReference<?>>> items) {
    this.items = items;
  }

  /**
   * Adds one item to the list.
   *
   * @param item the item to add.
   */
  public void addItem(Set<TCSResourceReference<?>> item) {
    items.add(item);
  }

  /**
   * Removes one item from the list.
   *
   * @param item the item to remove.
   */
  public void removeItem(Set<TCSResourceReference<?>> item) {
    items.remove(item);
  }

  @Override
  public void copyFrom(Property property) {
    ResourceProperty other = (ResourceProperty) property;
    List<Set<TCSResourceReference<?>>> items = new ArrayList<>(other.getItems());
    setItems(items);
  }

  @Override
  public String toString() {
    if (fValue != null) {
      return fValue.toString();
    }

    return items.stream()
        .flatMap(set -> set.stream())
        .map(r -> r.getName())
        .collect(Collectors.joining(", "));
  }

  @Override
  public Object clone() {
    ResourceProperty clone = (ResourceProperty) super.clone();
    List<Set<TCSResourceReference<?>>> items = new ArrayList<>(getItems());
    clone.setItems(items);

    return clone;
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/Layer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model.visualization;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;

/**
 * Describes a layer in a plant model which is used to group model elements.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Layer
    implements Serializable {

  /**
   * The unique ID of this layer.
   */
  private final int id;
  /**
   * The ordinal of this layer.
   * Layers with a higher ordinal are positioned above layers with a lower ordinal.
   */
  private final int ordinal;
  /**
   * Whether this layer is visible or not.
   */
  private final boolean visible;
  /**
   * The name of this layer.
   */
  private final String name;
  /**
   * The ID of the layer group this layer is assigned to.
   */
  private final int groupId;

  /**
   * Creates a new instance.
   *
   * @param id The unique ID of the layer.
   * @param ordinal The ordinal of the layer.
   * @param visible Whether the layer is visible or not.
   * @param name The name of the layer.
   * @param groupId The ID of the layer group the layer is assigned to.
   */
  public Layer(int id, int ordinal, boolean visible, String name, int groupId) {
    this.id = id;
    this.ordinal = ordinal;
    this.visible = visible;
    this.name = requireNonNull(name, "name");
    this.groupId = groupId;
  }

  /**
   * Returns the unique ID of this layer.
   *
   * @return The unique Id of this layer.
   */
  public int getId() {
    return id;
  }

  /**
   * Returns the ordinal of this layer.
   * Layers with a higher ordinal are positioned above layers with a lower ordinal.
   *
   * @return The ordinal of this layer.
   */
  public int getOrdinal() {
    return ordinal;
  }

  /**
   * Creates a copy of this object, with the given ordinal.
   *
   * @param ordinal The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Layer withOrdinal(int ordinal) {
    return new Layer(id, ordinal, visible, name, groupId);
  }

  /**
   * Returns whether this layer is visible or not.
   *
   * @return Whether this layer is visible or not.
   */
  public boolean isVisible() {
    return visible;
  }

  /**
   * Creates a copy of this object, with the given visible state.
   *
   * @param visible The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Layer withVisible(boolean visible) {
    return new Layer(id, ordinal, visible, name, groupId);
  }

  /**
   * Returns the name of this layer.
   *
   * @return The name of this layer.
   */
  public String getName() {
    return name;
  }

  /**
   * Creates a copy of this object, with the given name.
   *
   * @param name The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Layer withName(String name) {
    return new Layer(id, ordinal, visible, name, groupId);
  }

  /**
   * Returns the ID of the layer group this layer is assigned to.
   *
   * @return The ID of the layer group this layer is assigned to.
   */
  public int getGroupId() {
    return groupId;
  }

  /**
   * Creates a copy of this object, with the given group ID.
   *
   * @param groupId The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Layer withGroupId(int groupId) {
    return new Layer(id, ordinal, visible, name, groupId);
  }

  @Override
  public String toString() {
    return "Layer{" + ""
        + "id=" + id + ", "
        + "ordinal=" + ordinal + ", "
        + "visible=" + visible + ", "
        + "name=" + name +  ", "
        + "groupId=" + groupId + '}';
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/order/OrderSequenceCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.order;

import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.order.OrderConstants;

/**
 * A transfer object describing a transport order.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OrderSequenceCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * Indicates whether the name is incomplete and requires to be completed when creating the actual
   * order sequence.
   * (How exactly this is done is decided by the kernel.)
   */
  private final boolean incompleteName;
  /**
   * The type of the order sequence.
   */
  private String type = OrderConstants.TYPE_NONE;
  /**
   * The (optional) name of the vehicle that is supposed to execute the transport order.
   */
  @Nullable
  private String intendedVehicleName;
  /**
   * Whether failure of one transport order in the sequence makes subsequent ones fail, too.
   */
  private boolean failureFatal;

  /**
   * Creates a new instance.
   *
   * @param name The name of this transport order.
   */
  public OrderSequenceCreationTO(@Nonnull String name) {
    super(name);
    this.incompleteName = false;
  }

  private OrderSequenceCreationTO(@Nonnull String name,
                                  @Nonnull Map<String, String> properties,
                                  boolean incompleteName,
                                  @Nonnull String type,
                                  @Nullable String intendedVehicleName,
                                  boolean failureFatal) {
    super(name, properties);
    this.incompleteName = incompleteName;
    this.type = requireNonNull(type, "type");
    this.intendedVehicleName = intendedVehicleName;
    this.failureFatal = failureFatal;
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name the new name of the instance.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public OrderSequenceCreationTO withName(@Nonnull String name) {
    return new OrderSequenceCreationTO(name,
                                       getModifiableProperties(),
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given value.
   */
  @Override
  public OrderSequenceCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new OrderSequenceCreationTO(getName(),
                                       properties,
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public OrderSequenceCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new OrderSequenceCreationTO(getName(),
                                       propertiesWith(key, value),
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }

  /**
   * Indicates whether the name is incomplete and requires to be completed when creating the actual
   * order sequence.
   * (How exactly this is done is decided by the kernel.)
   *
   * @return <code>true</code> if, and only if, the name is incomplete and requires to be completed
   * by the kernel.
   */
  public boolean hasIncompleteName() {
    return incompleteName;
  }

  /**
   * Creates a copy of this object with the given <em>nameIncomplete</em> flag.
   *
   * @param incompleteName Whether the name is incomplete and requires to be completed when creating
   * the actual order sequence.
   *
   * @return A copy of this object, differing in the given value.
   */
  public OrderSequenceCreationTO withIncompleteName(boolean incompleteName) {
    return new OrderSequenceCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }

  /**
   * Returns the (optional) type of the order sequence.
   *
   * @return The (optional) type of the order sequence.
   */
  @Nonnull
  public String getType() {
    return type;
  }

  /**
   * Creates a copy of this object with the given type.
   *
   * @param type The type.
   * @return A copy of this object, differing in the given type.
   */
  public OrderSequenceCreationTO withType(@Nonnull String type) {
    return new OrderSequenceCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }

  /**
   * Returns the (optional) name of the vehicle that is supposed to execute the transport order.
   *
   * @return The (optional) name of the vehicle that is supposed to execute the transport order.
   */
  @Nullable
  public String getIntendedVehicleName() {
    return intendedVehicleName;
  }

  /**
   * Creates a copy of this object with the given
   * (optional) name of the vehicle that is supposed to execute the transport order.
   *
   * @param intendedVehicleName The vehicle name.
   * @return A copy of this object, differing in the given name of the intended vehicle.
   */
  public OrderSequenceCreationTO withIntendedVehicleName(@Nullable String intendedVehicleName) {
    return new OrderSequenceCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }

  /**
   * Returns whether failure of one transport order in the sequence makes subsequent ones fail, too.
   *
   * @return Whether failure of one transport order in the sequence makes subsequent ones fail, too.
   */
  public boolean isFailureFatal() {
    return failureFatal;
  }

  public OrderSequenceCreationTO withFailureFatal(boolean failureFatal) {
    return new OrderSequenceCreationTO(getName(),
                                       getModifiableProperties(),
                                       incompleteName,
                                       type,
                                       intendedVehicleName,
                                       failureFatal);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/ClientID.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import java.util.UUID;
import javax.annotation.Nonnull;

/**
 * Identifies a remote client unambiguously.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ClientID
implements Serializable {
  /**
   * The client's name.
   */
  private final String clientName;
  /**
   * The client's UUID.
   */
  private final UUID uuid;
  
  /**
   * Creates a new ClientID.
   *
   * @param clientName The client's name.
   */
  public ClientID(@Nonnull String clientName) {
    this.clientName = requireNonNull(clientName, "clientName");
    uuid = UUID.randomUUID();
  }
  
  /**
   * Return the client's name.
   *
   * @return The client's name.
   */
  @Nonnull
  public String getClientName() {
    return clientName;
  }
  
  /**
   * Checks if this object equals another one.
   *
   * @param otherObject The other object to be compared with this object.
   * @return <code>true</code> if, and only if, the given object is also a
   * <code>ClientID</code> and contains the same name and the same UUID as this
   * one.
   */
  @Override
  public boolean equals(Object otherObject) {
    if (otherObject instanceof ClientID) {
      ClientID otherID = (ClientID) otherObject;
      return clientName.equals(otherID.clientName) && uuid.equals(otherID.uuid);
    }
    else {
      return false;
    }
  }
  
  @Override
  public int hashCode() {
    return uuid.hashCode();
  }
  
  @Override
  public String toString() {
    return clientName + ":" + uuid;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/package-info.java<|end_filename|>
/**
 * Interfaces for pluggable strategies and other components for a kernel application.
 */
package org.opentcs.components.kernel;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/ParkingPositionToPriorityFunction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import com.google.common.base.Strings;
import java.util.function.Function;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.data.model.Point;

/**
 * Returns the priority of a parking position, if it has any, or <code>null</code>.
 * <p>
 * A priority is returned if the given point is a parking position and has a property with key
 * {@link Dispatcher#PROPKEY_PARKING_POSITION_PRIORITY} and a numeric (decimal) value as understood
 * by {@link Integer#parseInt(java.lang.String)}.
 * If these prerequisites are not met, <code>null</code> is returned.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ParkingPositionToPriorityFunction
    implements Function<Point, Integer> {

  /**
   * Creates a new instance.
   */
  public ParkingPositionToPriorityFunction() {
  }

  @Override
  public Integer apply(Point point) {
    if (!point.isParkingPosition()) {
      return null;
    }
    String priorityString = point.getProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY);
    if (Strings.isNullOrEmpty(priorityString)) {
      return null;
    }
    try {
      return Integer.parseInt(priorityString);
    }
    catch (NumberFormatException e) {
      return null;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/OtherGraphicalElement.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.ResourceBundle;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.model.AbstractModelComponent;

/**
 * A graphical component with illustrating effect, but without any impact
 * on the driving course.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class OtherGraphicalElement
    extends AbstractModelComponent {

  /**
   * Creates a new instance of OtherGraphicalElement.
   */
  public OtherGraphicalElement() {
    super();
  }

  @Override
  public String getDescription() {
    return ResourceBundle.getBundle(BUNDLE_PATH)
        .getString("otherGraphicalElement.description");
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/BlockSelector.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import java.awt.geom.Rectangle2D;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.persistence.ModelManager;

/**
 * A helper for selecting blocks/block elements.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class BlockSelector {

  /**
   * The application's model manager.
   */
  private final ModelManager modelManager;
  /**
   * The application's drawing editor.
   */
  private final OpenTCSDrawingEditor drawingEditor;

  /**
   * Creates a new instance.
   *
   * @param modelManager The application's model manager.
   * @param drawingEditor The application's drawing editor.
   */
  @Inject
  public BlockSelector(ModelManager modelManager, OpenTCSDrawingEditor drawingEditor) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
  }

  /**
   * Called when a block was selected, for instance in the tree view.
   * Should select all figures in the drawing view belonging to the block.
   *
   * @param block The selected block.
   */
  public void blockSelected(BlockModel block) {
    requireNonNull(block, "block");

    Rectangle2D r = null;

    List<Figure> blockElementFigures
        = ModelComponentUtil.getChildFigures(block, modelManager.getModel());

    for (Figure figure : blockElementFigures) {
      Rectangle2D displayBox = figure.getDrawingArea();

      if (r == null) {
        r = displayBox;
      }
      else {
        r.add(displayBox);
      }
    }

    if (r != null) {
      OpenTCSDrawingView drawingView = drawingEditor.getActiveView();

      drawingView.clearSelection();

      for (Figure figure : blockElementFigures) {
        drawingView.addToSelection(figure);
      }

      drawingView.updateBlock(block);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/guiceConfig/java/org/opentcs/guing/plugins/panels/loadgenerator/LoadGeneratorPanelModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Configures the load generator panel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoadGeneratorPanelModule
    extends PlantOverviewInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LoadGeneratorPanelModule.class);

  @Override
  protected void configure() {
    ContinuousLoadPanelConfiguration configuration
        = getConfigBindingProvider().get(ContinuousLoadPanelConfiguration.PREFIX,
                                         ContinuousLoadPanelConfiguration.class);

    if (!configuration.enable()) {
      LOG.info("Continuous load panel disabled by configuration.");
      return;
    }

    // tag::documentation_createPluginPanelModule[]
    pluggablePanelFactoryBinder().addBinding().to(ContinuousLoadPanelFactory.class);
    // end::documentation_createPluginPanelModule[]
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/VehicleTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(
    propOrder = {"name", "length", "energyLevelCritical", "energyLevelGood",
                 "energyLevelFullyRecharged", "energyLevelSufficientlyRecharged",
                 "maxVelocity", "maxReverseVelocity", "properties"})
public class VehicleTO
    extends PlantModelElementTO {

  //max velocity in mm/s.
  private int maxVelocity;
  //max rev velocity in mm/s.
  private int maxReverseVelocity;
  private Long length = 0L;
  private Long energyLevelCritical = 0L;
  private Long energyLevelGood = 0L;
  private Long energyLevelFullyRecharged = 0L;
  private Long energyLevelSufficientlyRecharged = 0L;

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getLength() {
    return length;
  }

  public VehicleTO setLength(@Nonnull Long length) {
    requireNonNull(length, "length");
    this.length = length;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getEnergyLevelCritical() {
    return energyLevelCritical;
  }

  public VehicleTO setEnergyLevelCritical(@Nonnull Long energyLevelCritical) {
    requireNonNull(energyLevelCritical, "energyLevelCritical");
    this.energyLevelCritical = energyLevelCritical;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getEnergyLevelGood() {
    return energyLevelGood;
  }

  public VehicleTO setEnergyLevelGood(@Nonnull Long energyLevelGood) {
    requireNonNull(energyLevelGood, "energyLevelGood");
    this.energyLevelGood = energyLevelGood;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getEnergyLevelFullyRecharged() {
    return energyLevelFullyRecharged;
  }

  public VehicleTO setEnergyLevelFullyRecharged(@Nonnull Long energyLevelFullyRecharged) {
    requireNonNull(energyLevelFullyRecharged, "energyLevelFullyRecharged");
    this.energyLevelFullyRecharged = energyLevelFullyRecharged;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getEnergyLevelSufficientlyRecharged() {
    return energyLevelSufficientlyRecharged;
  }

  public VehicleTO setEnergyLevelSufficientlyRecharged(
      @Nonnull Long energyLevelSufficientlyRecharged) {
    requireNonNull(energyLevelSufficientlyRecharged, "energyLevelSufficientlyRecharged");
    this.energyLevelSufficientlyRecharged = energyLevelSufficientlyRecharged;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public int getMaxVelocity() {
    return maxVelocity;
  }

  public VehicleTO setMaxVelocity(@Nonnull int maxVelocity) {
    this.maxVelocity = maxVelocity;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public int getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  public VehicleTO setMaxReverseVelocity(@Nonnull int maxReverseVelocity) {
    this.maxReverseVelocity = maxReverseVelocity;
    return this;
  }
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/exchange/ExchangeInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange;

import com.google.inject.AbstractModule;
import javax.inject.Singleton;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.common.DefaultPortalManager;
import org.opentcs.common.PortalManager;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.guing.exchange.adapter.OpsDeskVehicleAdapter;
import org.opentcs.guing.exchange.adapter.VehicleAdapter;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.opentcs.util.event.SimpleEventBus;

/**
 * A Guice configuration module for this package.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ExchangeInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {

    bind(PortalManager.class)
        .to(DefaultPortalManager.class)
        .in(Singleton.class);

    bind(KernelEventFetcher.class)
        .in(Singleton.class);

    EventBus eventBus = new SimpleEventBus();
    bind(EventSource.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(eventBus);
    bind(EventHandler.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(eventBus);
    bind(EventBus.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(eventBus);

    bind(SharedKernelServicePortalProvider.class)
        .to(ApplicationPortalProvider.class)
        .in(Singleton.class);

    bind(AttributeAdapterRegistry.class)
        .in(Singleton.class);
    bind(OpenTCSEventDispatcher.class)
        .in(Singleton.class);
    
    bind(DriveOrderHistory.class)
        .in(Singleton.class);
    
    bind(VehicleAdapter.class)
        .to(OpsDeskVehicleAdapter.class);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/order/Route.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.order;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A route for a {@link Vehicle}, consisting of a sequence of steps (pairs of {@link Path}s and
 * {@link Point}s) that need to be processed in their given order.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Route
    implements Serializable {

  /**
   * The sequence of steps this route consists of, in the order they are to be processed.
   */
  private final List<Step> steps;
  /**
   * The costs for travelling this route.
   */
  private final long costs;

  /**
   * Creates a new Route.
   *
   * @param routeSteps The sequence of steps this route consists of.
   * @param routeCosts The costs for travelling this route.
   */
  public Route(@Nonnull List<Step> routeSteps, long routeCosts) {
    requireNonNull(routeSteps, "routeSteps");
    checkArgument(!routeSteps.isEmpty(), "routeSteps may not be empty");
    steps = Collections.unmodifiableList(new ArrayList<>(routeSteps));
    costs = routeCosts;
  }

  /**
   * Returns the sequence of steps this route consists of.
   *
   * @return The sequence of steps this route consists of.
   * May be empty.
   * The returned <code>List</code> is unmodifiable.
   */
  @Nonnull
  public List<Step> getSteps() {
    return steps;
  }

  /**
   * Returns the costs for travelling this route.
   *
   * @return The costs for travelling this route.
   */
  public long getCosts() {
    return costs;
  }

  /**
   * Returns the final destination point that is reached by travelling this route.
   * (I.e. returns the destination point of this route's last step.)
   *
   * @return The final destination point that is reached by travelling this route.
   */
  @Nonnull
  public Point getFinalDestinationPoint() {
    return steps.get(steps.size() - 1).getDestinationPoint();
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Route)) {
      return false;
    }
    final Route other = (Route) o;
    return costs == other.costs
        && Objects.equals(steps, other.steps);
  }

  @Override
  public int hashCode() {
    return Objects.hash(steps, costs);
  }

  @Override
  public String toString() {
    return "Route{" + "steps=" + steps + ", costs=" + costs + '}';
  }

  /**
   * A single step in a route.
   */
  public static class Step
      implements Serializable {

    /**
     * The path to travel.
     */
    private final Path path;
    /**
     * The point that the vehicle is starting from.
     */
    private final Point sourcePoint;
    /**
     * The point that is reached by travelling the path.
     */
    private final Point destinationPoint;
    /**
     * The direction into which the vehicle is supposed to travel.
     */
    private final Vehicle.Orientation vehicleOrientation;
    /**
     * This step's index in the vehicle's route.
     */
    private final int routeIndex;
    /**
     * Whether execution of this step is allowed.
     */
    private final boolean executionAllowed;

    /**
     * Creates a new instance.
     *
     * @param path The path to travel.
     * @param srcPoint The point that the vehicle is starting from.
     * @param destPoint The point that is reached by travelling the path.
     * @param orientation The vehicle's orientation on this step.
     * @param routeIndex This step's index in the vehicle's route.
     * @param executionAllowed Whether execution of this step is allowed.
     */
    public Step(@Nullable Path path,
                @Nullable Point srcPoint,
                @Nonnull Point destPoint,
                @Nonnull Vehicle.Orientation orientation,
                int routeIndex,
                boolean executionAllowed) {
      this.path = path;
      this.sourcePoint = srcPoint;
      this.destinationPoint = requireNonNull(destPoint, "destPoint");
      this.vehicleOrientation = requireNonNull(orientation, "orientation");
      this.routeIndex = routeIndex;
      this.executionAllowed = executionAllowed;
    }

    /**
     * Creates a new instance.
     *
     * @param path The path to travel.
     * @param srcPoint The point that the vehicle is starting from.
     * @param destPoint The point that is reached by travelling the path.
     * @param orientation The vehicle's orientation on this step.
     * @param routeIndex This step's index in the vehicle's route.
     */
    public Step(@Nullable Path path,
                @Nullable Point srcPoint,
                @Nonnull Point destPoint,
                @Nonnull Vehicle.Orientation orientation,
                int routeIndex) {
      this(path, srcPoint, destPoint, orientation, routeIndex, true);
    }

    /**
     * Returns the path to travel.
     *
     * @return The path to travel. May be <code>null</code> if the vehicle does
     * not really have to move.
     */
    @Nullable
    public Path getPath() {
      return path;
    }

    /**
     * Returns the point that the vehicle is starting from.
     *
     * @return The point that the vehicle is starting from.
     * May be <code>null</code> if the vehicle does not really have to move.
     */
    @Nullable
    public Point getSourcePoint() {
      return sourcePoint;
    }

    /**
     * Returns the point that is reached by travelling the path.
     *
     * @return The point that is reached by travelling the path.
     */
    @Nonnull
    public Point getDestinationPoint() {
      return destinationPoint;
    }

    /**
     * Returns the direction into which the vehicle is supposed to travel.
     *
     * @return The direction into which the vehicle is supposed to travel.
     */
    @Nonnull
    public Vehicle.Orientation getVehicleOrientation() {
      return vehicleOrientation;
    }

    /**
     * Returns this step's index in the vehicle's route.
     *
     * @return This step's index in the vehicle's route.
     */
    public int getRouteIndex() {
      return routeIndex;
    }

    /**
     * Returns whether execution of this step is allowed.
     *
     * @return {@code true}, if execution of this step is allowed, otherwise {@code false}.
     */
    public boolean isExecutionAllowed() {
      return executionAllowed;
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof Step)) {
        return false;
      }
      Step other = (Step) o;
      return Objects.equals(path, other.path)
          && Objects.equals(sourcePoint, other.sourcePoint)
          && Objects.equals(destinationPoint, other.destinationPoint)
          && Objects.equals(vehicleOrientation, other.vehicleOrientation)
          && routeIndex == other.routeIndex;
    }

    @Override
    public int hashCode() {
      return Objects.hash(path, sourcePoint, destinationPoint, vehicleOrientation, routeIndex);
    }

    @Override
    public String toString() {
      return destinationPoint.getName();
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/menus/menubar/ActionsMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import java.awt.event.ActionEvent;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.action.actions.CreatePeripheralJobAction;
import org.opentcs.guing.application.action.actions.CreateTransportOrderAction;
import org.opentcs.guing.application.action.actions.FindVehicleAction;
import org.opentcs.guing.application.menus.MenuFactory;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.components.drawing.figures.VehicleFigure;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.guing.util.PlantOverviewOperatingApplicationConfiguration;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's menu for run-time actions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ActionsMenu
    extends JMenu {

  /**
   * A menu item for creating new transport orders.
   */
  private final JMenuItem menuItemCreateTransportOrder;
  /**
   * A menu item for creating new peripheral jobs.
   */
  private final JMenuItem menuItemCreatePeripheralJob;
  /**
   * A menu item for finding a vehicle in the driving course.
   */
  private final JMenuItem menuItemFindVehicle;
  /**
   * A check box for ignoring the vehicles' precise positions.
   */
  private final JCheckBoxMenuItem cbiIgnorePrecisePosition;
  /**
   * A check box for ignoring the vehicles' orientation angles.
   */
  private final JCheckBoxMenuItem cbiIgnoreOrientationAngle;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   * @param drawingEditor The application's drawing editor.
   * @param menuFactory A factory for menu items.
   * @param appConfig The application's configuration.
   */
  @Inject
  public ActionsMenu(ViewActionMap actionMap,
                     OpenTCSDrawingEditor drawingEditor,
                     MenuFactory menuFactory,
                     PlantOverviewOperatingApplicationConfiguration appConfig) {
    requireNonNull(actionMap, "actionMap");
    requireNonNull(drawingEditor, "drawingEditor");
    requireNonNull(menuFactory, "menuFactory");
    requireNonNull(appConfig, "appConfig");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.MENU_PATH);

    this.setText(labels.getString("actionsMenu.text"));
    this.setToolTipText(labels.getString("actionsMenu.tooltipText"));
    this.setMnemonic('A');

    // Menu item Actions -> Create Transport Order
    menuItemCreateTransportOrder = new JMenuItem(actionMap.get(CreateTransportOrderAction.ID));
    add(menuItemCreateTransportOrder);
    //Menu item Actions ->  Create Peripheral Job.
    menuItemCreatePeripheralJob = new JMenuItem(actionMap.get(CreatePeripheralJobAction.ID));
    add(menuItemCreatePeripheralJob);
    addSeparator();

    // Menu item Actions -> Find Vehicle
    menuItemFindVehicle = new JMenuItem(actionMap.get(FindVehicleAction.ID));
    add(menuItemFindVehicle);

    // Menu item Actions -> Ignore precise position
    cbiIgnorePrecisePosition
        = new JCheckBoxMenuItem(labels.getString("actionsMenu.menuItem_ignorePrecisePosition.text"));

    add(cbiIgnorePrecisePosition);
    cbiIgnorePrecisePosition.setSelected(appConfig.ignoreVehiclePrecisePosition());
    cbiIgnorePrecisePosition.addActionListener((ActionEvent e) -> {
      for (Figure figure : drawingEditor.getDrawing().getChildren()) {
        if (figure instanceof VehicleFigure) {
          ((VehicleFigure) figure).setIgnorePrecisePosition(cbiIgnorePrecisePosition.isSelected());
        }
      }
    });

    // Menu item Actions -> Ignore orientation angle
    cbiIgnoreOrientationAngle
        = new JCheckBoxMenuItem(labels.getString("actionsMenu.menuItem_ignorePreciseOrientation.text"));

    add(cbiIgnoreOrientationAngle);
    cbiIgnoreOrientationAngle.setSelected(appConfig.ignoreVehicleOrientationAngle());
    cbiIgnoreOrientationAngle.addActionListener((ActionEvent e) -> {
      for (Figure figure : drawingEditor.getDrawing().getChildren()) {
        if (figure instanceof VehicleFigure) {
          ((VehicleFigure) figure).setIgnoreOrientationAngle(cbiIgnoreOrientationAngle.isSelected());
        }
      }
    });
  }
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/StandardRemotePeripheralService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.access.rmi.services.RegistrationName;
import org.opentcs.access.rmi.services.RemotePeripheralService;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is the standard implementation of the {@link RemotePeripheralService} interface.
 * <p>
 * Upon creation, an instance of this class registers itself with the RMI registry by the name
 * {@link RegistrationName#REMOTE_PERIPHERAL_SERVICE}.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardRemotePeripheralService
    extends StandardRemoteTCSObjectService
    implements RemotePeripheralService {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StandardRemotePeripheralService.class);
  /**
   * The peripheral service to invoke methods on.
   */
  private final PeripheralService peripheralService;
  /**
   * The user manager.
   */
  private final UserManager userManager;
  /**
   * Provides configuration data.
   */
  private final RmiKernelInterfaceConfiguration configuration;
  /**
   * Provides socket factories used for RMI.
   */
  private final SocketFactoryProvider socketFactoryProvider;
  /**
   * Provides the registry with which this remote service registers.
   */
  private final RegistryProvider registryProvider;
  /**
   * Executes tasks modifying kernel data.
   */
  private final ExecutorService kernelExecutor;
  /**
   * The registry with which this remote service registers.
   */
  private Registry rmiRegistry;
  /**
   * Whether this remote service is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param peripheralService The peripheral service.
   * @param userManager The user manager.
   * @param configuration This class' configuration.
   * @param socketFactoryProvider The socket factory provider used for RMI.
   * @param registryProvider The provider for the registry with which this remote service registers.
   * @param kernelExecutor Executes tasks modifying kernel data.
   */
  @Inject
  public StandardRemotePeripheralService(PeripheralService peripheralService,
                                         UserManager userManager,
                                         RmiKernelInterfaceConfiguration configuration,
                                         SocketFactoryProvider socketFactoryProvider,
                                         RegistryProvider registryProvider,
                                         @KernelExecutor ExecutorService kernelExecutor) {
    super(peripheralService, userManager, kernelExecutor);
    this.peripheralService = requireNonNull(peripheralService, "peripheralService");
    this.userManager = requireNonNull(userManager, "userManager");
    this.configuration = requireNonNull(configuration, "configuration");
    this.socketFactoryProvider = requireNonNull(socketFactoryProvider, "socketFactoryProvider");
    this.registryProvider = requireNonNull(registryProvider, "registryProvider");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    rmiRegistry = registryProvider.get();

    // Export this instance via RMI.
    try {
      LOG.debug("Exporting proxy...");
      UnicastRemoteObject.exportObject(this,
                                       configuration.remotePeripheralServicePort(),
                                       socketFactoryProvider.getClientSocketFactory(),
                                       socketFactoryProvider.getServerSocketFactory());
      LOG.debug("Binding instance with RMI registry...");
      rmiRegistry.rebind(RegistrationName.REMOTE_PERIPHERAL_SERVICE, this);
    }
    catch (RemoteException exc) {
      LOG.error("Could not export or bind with RMI registry", exc);
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    try {
      LOG.debug("Unbinding from RMI registry...");
      rmiRegistry.unbind(RegistrationName.REMOTE_PERIPHERAL_SERVICE);
      LOG.debug("Unexporting RMI interface...");
      UnicastRemoteObject.unexportObject(this, true);
    }
    catch (RemoteException | NotBoundException exc) {
      LOG.warn("Exception shutting down RMI interface", exc);
    }

    initialized = false;
  }

  @Override
  public void attachCommAdapter(ClientID clientId,
                                TCSResourceReference<Location> ref,
                                PeripheralCommAdapterDescription description) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_PERIPHERALS);

    try {
      kernelExecutor.submit(() -> peripheralService.attachCommAdapter(ref, description)).get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }

  @Override
  public void disableCommAdapter(ClientID clientId, TCSResourceReference<Location> ref) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_PERIPHERALS);

    try {
      kernelExecutor.submit(() -> peripheralService.disableCommAdapter(ref)).get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }

  @Override
  public void enableCommAdapter(ClientID clientId, TCSResourceReference<Location> ref) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_PERIPHERALS);

    try {
      kernelExecutor.submit(() -> peripheralService.enableCommAdapter(ref)).get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }

  @Override
  public PeripheralAttachmentInformation fetchAttachmentInformation(
      ClientID clientId,
      TCSResourceReference<Location> ref) {
    userManager.verifyCredentials(clientId, UserPermission.READ_DATA);

    return peripheralService.fetchAttachmentInformation(ref);
  }

  @Override
  public PeripheralProcessModel fetchProcessModel(ClientID clientId,
                                                  TCSResourceReference<Location> ref) {
    userManager.verifyCredentials(clientId, UserPermission.READ_DATA);

    return peripheralService.fetchProcessModel(ref);
  }

  @Override
  public void sendCommAdapterCommand(ClientID clientId,
                                     TCSResourceReference<Location> ref,
                                     PeripheralAdapterCommand command) {
    userManager.verifyCredentials(clientId, UserPermission.MODIFY_PERIPHERALS);

    try {
      kernelExecutor.submit(() -> peripheralService.sendCommAdapterCommand(ref, command)).get();
    }
    catch (InterruptedException | ExecutionException exc) {
      throw findSuitableExceptionFor(exc);
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/orders/TransportOrderContainerListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.orders;

import java.util.Collection;
import org.opentcs.data.order.TransportOrder;

/**
 * Listener for changes in the {@link TransportOrdersContainerPanel}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface TransportOrderContainerListener {

  /**
   * Notifies the listener that the container has been initialized.
   *
   * @param orders The orders the container has been initialized with.
   */
  void containerInitialized(Collection<TransportOrder> orders);

  /**
   * Notifies the listener that a transport order has been added.
   *
   * @param order The transport order that has been added.
   */
  void transportOrderAdded(TransportOrder order);

  /**
   * Notifies the listener that a transport order has been updated.
   *
   * @param order The transport order that has been updated.
   */
  void transportOrderUpdated(TransportOrder order);

  /**
   * Notifies the listener that a transport order has been removed.
   *
   * @param order The transport order that has been removed.
   */
  void transportOrderRemoved(TransportOrder order);

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/management/ProcessModelEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.management;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.drivers.vehicle.VehicleProcessModel;

/**
 * Instances of this class represent events emitted by/for changes on {@link VehicleProcessModel}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ProcessModelEvent
    extends CommAdapterEvent
    implements Serializable {

  /**
   * The attribute's name that changed in the process model.
   */
  private final String attributeChanged;
  /**
   * A serializable representation of the corresponding process model.
   */
  private final VehicleProcessModelTO updatedProcessModel;

  /**
   * Creates a new instance.
   *
   * @param attributeChanged The attribute's name that changed.
   * @param updatedProcessModel A serializable representation of the corresponding process model.
   */
  public ProcessModelEvent(@Nonnull String attributeChanged,
                           @Nonnull VehicleProcessModelTO updatedProcessModel) {
    this.attributeChanged = requireNonNull(attributeChanged, "attributeChanged");
    this.updatedProcessModel = requireNonNull(updatedProcessModel, "updatedProcessModel");
  }

  /**
   * Returns the attribute's name that changed in the process model.
   *
   * @return The attribute's name that changed in the process model.
   */
  public String getAttributeChanged() {
    return attributeChanged;
  }

  /**
   * Returns a serializable representation of the corresponding process model.
   *
   * @return A serializable representation of the corresponding process model.
   */
  public VehicleProcessModelTO getUpdatedProcessModel() {
    return updatedProcessModel;
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/TransportOrderTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.table.AbstractTableModel;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import static org.opentcs.guing.plugins.panels.loadgenerator.I18nPlantOverviewPanelLoadGenerator.BUNDLE_PATH;
import org.opentcs.guing.plugins.panels.loadgenerator.xmlbinding.TransportOrderEntry;
import org.opentcs.guing.plugins.panels.loadgenerator.xmlbinding.TransportOrdersDocument;

/**
 * A table model for transport orders.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class TransportOrderTableModel
    extends AbstractTableModel {

  /**
   * This classe's bundle.
   */
  private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * The column names.
   */
  private static final String[] COLUMN_NAMES = new String[] {
    "#",
    BUNDLE.getString("transportOrderTableModel.column_deadline.headerText"),
    BUNDLE.getString("transportOrderTableModel.column_vehicle.headerText")};
  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[] {
    Integer.class,
    TransportOrderData.Deadline.class,
    TCSObjectReference.class,};
  /**
   * The actual content.
   */
  private final List<TransportOrderData> transportOrderDataList = new ArrayList<>();

  /**
   * Creates a new instance.
   */
  public TransportOrderTableModel() {
  }

  /**
   * Adds a <code>TransportOrderData</code>.
   *
   * @param data The new transport order data
   */
  public void addData(TransportOrderData data) {
    int newIndex = transportOrderDataList.size();
    transportOrderDataList.add(data);
    fireTableRowsInserted(newIndex, newIndex);
  }

  /**
   * Removes a <code>TransportOrderData</code>.
   *
   * @param row Index indicating which transport order data shall be removed
   */
  public void removeData(int row) {
    transportOrderDataList.remove(row);
    fireTableRowsDeleted(row, row);
  }

  /**
   * Returns the <code>TransportOrderData</code> at the given index.
   *
   * @param row Index indicating which data shall be returned
   * @return The transport order data at the given index
   */
  public TransportOrderData getDataAt(int row) {
    if (row >= 0) {
      return transportOrderDataList.get(row);
    }
    else {
      return null;
    }
  }

  @Override
  public int getRowCount() {
    return transportOrderDataList.size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    TransportOrderData data = transportOrderDataList.get(rowIndex);

    switch (columnIndex) {
      case 0:
        return rowIndex + 1;
      case 1:
        return data.getDeadline();
      case 2:
        return data.getIntendedVehicle();
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case 0:
        return false;
      case 1:
        return true;
      case 2:
        return true;
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    TransportOrderData data = transportOrderDataList.get(rowIndex);
    switch (columnIndex) {
      case 1:
        data.setDeadline((TransportOrderData.Deadline) aValue);
        break;
      case 2:
        data.setIntendedVehicle((TCSObjectReference<Vehicle>) aValue);
        break;
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  public TransportOrdersDocument toXmlDocument() {
    TransportOrdersDocument result = new TransportOrdersDocument();

    for (TransportOrderData curData : transportOrderDataList) {
      result.getTransportOrders().add(new TransportOrderEntry(
              curData.getDeadline(),
              curData.getDriveOrders(),
              curData.getIntendedVehicle() == null ? null : curData.getIntendedVehicle().getName(),
              curData.getProperties())
      );
    }

    return result;
  }

  /**
   * Returns the list containing all <code>TransportOrderData</code>.
   *
   * @return The list containing all data
   */
  public List<TransportOrderData> getList() {
    return transportOrderDataList;
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/drawing/figures/VehicleFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import com.google.inject.assistedinject.Assisted;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ImageObserver;
import static java.awt.image.ImageObserver.ABORT;
import static java.awt.image.ImageObserver.ALLBITS;
import static java.awt.image.ImageObserver.FRAMEBITS;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.SwingUtilities;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.handle.Handle;
import org.jhotdraw.geom.BezierPath;
import org.opentcs.components.plantoverview.VehicleTheme;
import org.opentcs.data.model.Triple;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.menus.MenuFactory;
import org.opentcs.guing.application.menus.VehiclePopupMenu;
import org.opentcs.guing.components.dialogs.SingleVehicleView;
import org.opentcs.guing.components.drawing.ZoomPoint;
import org.opentcs.guing.components.drawing.figures.decoration.VehicleOutlineHandle;
import org.opentcs.guing.components.drawing.figures.liner.TripleBezierLiner;
import org.opentcs.guing.components.drawing.figures.liner.TupelBezierLiner;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.components.properties.type.AngleProperty;
import org.opentcs.guing.model.SimpleFolder;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.AbstractConnection;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.PlantOverviewOperatingApplicationConfiguration;

/**
 * The graphical representation of a vehicle.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleFigure
    extends TCSFigure
    implements AttributesChangeListener,
               ImageObserver {

  /**
   * When the position of the vehicle changed.
   */
  public static final String POSITION_CHANGED = "position_changed";
  /**
   * The figure's length in drawing units.
   */
  private static final double LENGTH = 30.0;
  /**
   * The figure's width in drawing units.
   */
  private static final double WIDTH = 20.0;
  /**
   * The vehicle theme to be used.
   */
  private final VehicleTheme vehicleTheme;
  /**
   * A factory for popup menus.
   */
  private final MenuFactory menuFactory;
  /**
   * The tool tip text generator.
   */
  private final ToolTipTextGenerator textGenerator;
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The application's current state.
   */
  private final ApplicationState applicationState;
  /**
   * The angle at which the image is to be drawn.
   */
  private double fAngle;
  /**
   * The image.
   */
  protected transient Image fImage;
  /**
   * Whether to ignore the vehicle's precise position or not.
   */
  private boolean ignorePrecisePosition;
  /**
   * Whether to ignore the vehicle's orientation angle or not.
   */
  private boolean ignoreOrientationAngle;
  /**
   * Indicates whether figure details changed.
   */
  private boolean figureDetailsChanged = false;

  /**
   * Creates a new instance.
   *
   * @param vehicleTheme The vehicle theme to be used.
   * @param menuFactory A factory for popup menus.
   * @param appConfig The application's configuration.
   * @param model The model corresponding to this graphical object.
   * @param textGenerator The tool tip text generator.
   * @param modelManager The model manager.
   * @param applicationState The application's current state.
   */
  @Inject
  public VehicleFigure(VehicleTheme vehicleTheme,
                       MenuFactory menuFactory,
                       PlantOverviewOperatingApplicationConfiguration appConfig,
                       @Assisted VehicleModel model,
                       ToolTipTextGenerator textGenerator,
                       ModelManager modelManager,
                       ApplicationState applicationState) {
    super(model);
    this.vehicleTheme = requireNonNull(vehicleTheme, "vehicleTheme");
    this.menuFactory = requireNonNull(menuFactory, "menuFactory");
    this.textGenerator = requireNonNull(textGenerator, "textGenerator");
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.applicationState = requireNonNull(applicationState, "applicationState");

    fDisplayBox = new Rectangle((int) LENGTH, (int) WIDTH);
    fZoomPoint = new ZoomPoint(0.5 * LENGTH, 0.5 * WIDTH);

    setIgnorePrecisePosition(appConfig.ignoreVehiclePrecisePosition());
    setIgnoreOrientationAngle(appConfig.ignoreVehicleOrientationAngle());

    fImage = vehicleTheme.statelessImage(model.getVehicle());
  }

  @Override
  public VehicleModel getModel() {
    return (VehicleModel) get(FigureConstants.MODEL);
  }

  public void setAngle(double angle) {
    fAngle = angle;
  }

  public double getAngle() {
    return fAngle;
  }

  @Override
  public Rectangle2D.Double getBounds() {
    Rectangle2D.Double r2d = new Rectangle2D.Double();
    r2d.setRect(fDisplayBox.getBounds2D());

    return r2d;
  }

  @Override
  public Object getTransformRestoreData() {
    return fDisplayBox.clone();
  }

  @Override
  public void restoreTransformTo(Object restoreData) {
    Rectangle r = (Rectangle) restoreData;
    fDisplayBox.x = r.x;
    fDisplayBox.y = r.y;
    fDisplayBox.width = r.width;
    fDisplayBox.height = r.height;
    fZoomPoint.setX(r.getCenterX());
    fZoomPoint.setY(r.getCenterY());
  }

  @Override
  public void transform(AffineTransform tx) {
    Point2D center = fZoomPoint.getPixelLocationExactly();
    setBounds((Point2D.Double) tx.transform(center, center), null);
  }

  @Override
  public String getToolTipText(Point2D.Double p) {
    return textGenerator.getToolTipText(getModel());
  }

  /**
   * Sets the ignore flag for the vehicle's reported orientation angle.
   *
   * @param doIgnore Whether to ignore the reported orientation angle.
   */
  public final void setIgnoreOrientationAngle(boolean doIgnore) {
    ignoreOrientationAngle = doIgnore;
    PointModel point = getModel().getPoint();

    if (point == null) {
      // Only draw the vehicle if the point is known or the precise position is to be used.
      setVisible(!ignorePrecisePosition);
    }
    else {
      Figure pointFigure = modelManager.getModel().getFigure(point);
      Rectangle2D.Double r = pointFigure.getBounds();
      Point2D.Double pCenter = new Point2D.Double(r.getCenterX(), r.getCenterY());
      setBounds(pCenter, null);
      fireFigureChanged();
    }
  }

  /**
   * Sets the ignore flag for the vehicle's precise position.
   *
   * @param doIgnore Whether to ignore the reported precise position of the
   * vehicle.
   */
  public final void setIgnorePrecisePosition(boolean doIgnore) {
    ignorePrecisePosition = doIgnore;
    PointModel point = getModel().getPoint();

    if (point == null) {
      // Only draw the vehicle if the point is known or the precise position is to be used.
      setVisible(!ignorePrecisePosition);
    }
    else {
      Figure pointFigure = modelManager.getModel().getFigure(point);
      Rectangle2D.Double r = pointFigure.getBounds();
      Point2D.Double pCenter = new Point2D.Double(r.getCenterX(), r.getCenterY());
      setBounds(pCenter, null);
      fireFigureChanged();
    }
  }

  /**
   * Draws the center of the figure at <code>anchor</code>; the size does not
   * change.
   *
   * @param anchor Center of the figure
   * @param lead Not used
   */
  @Override
  public void setBounds(Point2D.Double anchor, Point2D.Double lead) {
    VehicleModel model = getModel();
    Rectangle2D.Double oldBounds = getBounds();
    setVisible(false);

    Triple precisePosition = model.getPrecisePosition();

    if (!ignorePrecisePosition) {
      if (precisePosition != null) {
        setVisible(true);
        // Tree-Folder "Vehicles"
        SimpleFolder folder = (SimpleFolder) model.getParent();
        SystemModel systemModel = (SystemModel) folder.getParent();
        double scaleX = systemModel.getDrawingMethod().getOrigin().getScaleX();
        double scaleY = systemModel.getDrawingMethod().getOrigin().getScaleY();

        if (scaleX != 0.0 && scaleY != 0.0) {
          anchor.x = precisePosition.getX() / scaleX;
          anchor.y = -precisePosition.getY() / scaleY;
        }
      }
    }

    fZoomPoint.setX(anchor.x);
    fZoomPoint.setY(anchor.y);
    fDisplayBox.x = (int) (anchor.x - 0.5 * LENGTH);
    fDisplayBox.y = (int) (anchor.y - 0.5 * WIDTH);
    firePropertyChange(POSITION_CHANGED, oldBounds, getBounds());

    updateVehicleOrientation();
  }

  private void updateVehicleOrientation() {
    VehicleModel model = getModel();
    // orientation:
    // 1. Use exact orientation from vehicle adapter.
    // 2. Use orientation from current point.
    // 3. Use direction to next point.
    // 4. Use last known orientation.
    double angle = model.getOrientationAngle();
    PointModel currentPoint = model.getPoint();

    if (currentPoint != null) {
      setVisible(true);
    }

    if (!Double.isNaN(angle) && !ignoreOrientationAngle) {
      fAngle = angle;
    }
    else if (currentPoint != null) {
      // Use orientation from current point.
      AngleProperty ap = currentPoint.getPropertyVehicleOrientationAngle();
      angle = (double) ap.getValue();

      if (!Double.isNaN(angle)) {
        fAngle = angle;
      }
      else {
        alignVehicleToNextPoint();
      }
    }
  }

  private void alignVehicleToNextPoint() {
    VehicleModel model = getModel();
    PointModel nextPoint = model.getNextPoint();
    PointModel currentPoint = model.getPoint();

    AbstractConnection connection;
    if (model.getDriveOrderState() == TransportOrder.State.BEING_PROCESSED) {
      connection = model.getCurrentDriveOrderPath();
    }
    else {
      if (nextPoint != null) {
        connection = currentPoint.getConnectionTo(nextPoint);
      }
      else {
        // No destination point, use a random point connected to the current point.
        connection = currentPoint.getConnections().stream()
            .filter(con -> con instanceof PathModel)
            .filter(con -> Objects.equals(con.getStartComponent(), currentPoint))
            .findFirst()
            .orElse(null);
      }
    }

    if (connection != null) {
      fAngle = calculateAngle(connection);
    }
  }

  private double calculateAngle(AbstractConnection connection) {
    PointModel currentPoint = (PointModel) connection.getStartComponent();
    PointModel nextPoint = (PointModel) connection.getEndComponent();

    PathConnection pathFigure
        = (PathConnection) modelManager.getModel().getFigure(connection);
    LabeledPointFigure clpf
        = (LabeledPointFigure) modelManager.getModel().getFigure(currentPoint);
    PointFigure cpf = clpf.getPresentationFigure();

    if (pathFigure.getLiner() instanceof TupelBezierLiner
        || pathFigure.getLiner() instanceof TripleBezierLiner) {
      BezierPath bezierPath = pathFigure.getBezierPath();
      Point2D.Double cp = bezierPath.get(0, BezierPath.C2_MASK);
      double dx = cp.getX() - cpf.getZoomPoint().getX();
      double dy = cp.getY() - cpf.getZoomPoint().getY();
      return Math.toDegrees(Math.atan2(-dy, dx));
    }
    else {
      LabeledPointFigure nlpf
          = (LabeledPointFigure) modelManager.getModel().getFigure(nextPoint);
      PointFigure npf = nlpf.getPresentationFigure();
      double dx = npf.getZoomPoint().getX() - cpf.getZoomPoint().getX();
      double dy = npf.getZoomPoint().getY() - cpf.getZoomPoint().getY();
      return Math.toDegrees(Math.atan2(-dy, dx));
    }
  }

  /**
   * Forces the vehicle figure to be drawn. (Used primarily for {@link SingleVehicleView}.)
   *
   * @param g2d The graphics context.
   */
  public void forcedDraw(Graphics2D g2d) {
    drawFill(g2d);
  }

  @Override
  protected void drawFigure(Graphics2D g2d) {
    VehicleModel model = getModel();
    PointModel currentPoint = model.getPoint();
    Triple precisePosition = model.getPrecisePosition();
    if (currentPoint != null || precisePosition != null) {
      drawFill(g2d);
    }
  }

  @Override
  protected void drawFill(Graphics2D g2d) {
    if (g2d == null) {
      return;
    }

    int dx;
    int dy;
    Rectangle r = displayBox();

    if (fImage != null) {
      dx = (r.width - fImage.getWidth(this)) / 2;
      dy = (r.height - fImage.getHeight(this)) / 2;
      int x = r.x + dx;
      int y = r.y + dy;
      AffineTransform oldAF = g2d.getTransform();
      g2d.translate(r.getCenterX(), r.getCenterY());
      g2d.rotate(-Math.toRadians(fAngle));
      g2d.translate(-r.getCenterX(), -r.getCenterY());
      g2d.drawImage(fImage, x, y, null);
      g2d.setTransform(oldAF);
    }
    else {
      // TODO: Draw an outline, e.g. a rectangle.
    }
  }

  @Override
  protected void drawStroke(Graphics2D g2d) {
    // Nothing to do here - Vehicle Figure is completely drawn in drawFill()
  }

  @Override
  public Collection<Handle> createHandles(int detailLevel) {
    LinkedList<Handle> handles = new LinkedList<>();

    switch (detailLevel) {
      case -1: // Mouse Moved
        handles.add(new VehicleOutlineHandle(this));
        break;

      case 0:  // Mouse clicked
//      handles.add(new VehicleOutlineHandle(this));
        break;

      case 1:  // Double-Click
//      handles.add(new VehicleOutlineHandle(this));
        break;

      default:
        break;
    }

    return handles;
  }

  @Override
  public boolean handleMouseClick(Point2D.Double p,
                                  MouseEvent evt,
                                  DrawingView drawingView) {
    // This gets executed on a double click AND a right click on the figure
    VehicleModel model = getModel();
    VehiclePopupMenu menu = menuFactory.createVehiclePopupMenu(Arrays.asList(model));
    menu.show(drawingView.getComponent(), evt.getX(), evt.getY());

    return false;
  }

  @Override
  public void propertiesChanged(AttributesChangeEvent e) {
    if (e.getInitiator().equals(this)
        || e.getModel() == null) {
      return;
    }

    updateFigureDetails((VehicleModel) e.getModel());

    if (isFigureDetailsChanged()) {
      SwingUtilities.invokeLater(() -> {
        // Only call if the figure is visible - will cause NPE in BoundsOutlineHandle otherwise.
        if (isVisible()) {
          fireFigureChanged();
        }
      });

      setFigureDetailsChanged(false);
    }
  }

  /**
   * Updates the figure details based on the given vehicle model.
   * <p>
   * If figure details do change, call {@link #setFigureDetailsChanged(boolean)} to set the
   * corresponding flag to {@code true}.
   * When overriding this method, always remember to call the super-implementation.
   * </p>
   *
   * @param model The updated vehicle model.
   */
  protected void updateFigureDetails(VehicleModel model) {
  }

  @Override
  public boolean imageUpdate(Image img, int infoflags,
                             int x, int y,
                             int width, int height) {
    if ((infoflags & (FRAMEBITS | ALLBITS)) != 0) {
      invalidate();
    }

    return (infoflags & (ALLBITS | ABORT)) == 0;
  }

  /**
   * Returns the vehicle theme.
   *
   * @return The vehicle theme.
   */
  protected VehicleTheme getVehicleTheme() {
    return vehicleTheme;
  }

  public boolean isFigureDetailsChanged() {
    return figureDetailsChanged;
  }

  public void setFigureDetailsChanged(boolean figureDetailsChanged) {
    this.figureDetailsChanged = figureDetailsChanged;
  }

  public boolean isIgnorePrecisePosition() {
    return ignorePrecisePosition;
  }

  public ModelManager getModelManager() {
    return modelManager;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/notification/UserNotification.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.notification;

import java.io.Serializable;
import java.time.Instant;
import java.util.Objects;
import javax.annotation.Nullable;

/**
 * A notification to be read by a user.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class UserNotification
    implements Serializable {

  /**
   * An identifier of the notification's source.
   */
  @Nullable
  private final String source;
  /**
   * This message's text.
   */
  private final String text;
  /**
   * This message's type.
   */
  private final Level level;
  /**
   * This message's creation timestamp.
   */
  private final Instant timestamp;

  /**
   * Creates a new Message.
   *
   * @param source An identifier of the notification's source.
   * @param text The actual message text.
   * @param level The new message's level.
   */
  public UserNotification(@Nullable String source, String text, Level level) {
    this.source = source;
    this.text = Objects.requireNonNull(text, "text");
    this.level = Objects.requireNonNull(level, "level");
    this.timestamp = Instant.now();
  }

  /**
   * Creates a new Message.
   *
   * @param text The actual message text.
   * @param level The new message's level.
   */
  public UserNotification(String text, Level level) {
    this(null, text, level);
  }

  /**
   * Returns this notification's (optional) source.
   *
   * @return This notification's (optional) source.
   */
  @Nullable
  public String getSource() {
    return source;
  }

  /**
   * Returns this message's text.
   *
   * @return This message's text.
   */
  public String getText() {
    return text;
  }

  /**
   * Returns this message's type.
   *
   * @return This message's type.
   */
  public Level getLevel() {
    return level;
  }

  /**
   * Returns this message's creation timestamp.
   *
   * @return This message's creation timestamp.
   */
  public Instant getTimestamp() {
    return timestamp;
  }

  @Override
  public int hashCode() {
    int hash = 5;
    hash = 89 * hash + Objects.hashCode(this.text);
    hash = 89 * hash + Objects.hashCode(this.level);
    hash = 89 * hash + Objects.hashCode(this.timestamp);
    return hash;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o instanceof UserNotification) {
      UserNotification other = (UserNotification) o;
      return Objects.equals(this.source, other.source)
          && Objects.equals(this.text, other.text)
          && Objects.equals(this.level, other.level)
          && Objects.equals(this.timestamp, other.timestamp);
    }
    return false;
  }

  @Override
  public String toString() {
    return "UserNotification{"
        + "source=" + source
        + ", timestamp=" + timestamp
        + ", level=" + level
        + ", text=" + text
        + '}';
  }

  /**
   * Defines the possible message types.
   */
  public enum Level {

    /**
     * Marks usual, informational content.
     */
    INFORMATIONAL,
    /**
     * Marks unusual content a user would probably be interested in.
     */
    NOTEWORTHY,
    /**
     * Marks important content the user should not miss.
     */
    IMPORTANT
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-Statistics/src/main/java/org/opentcs/guing/plugins/panels/statistics/StatisticsPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.statistics;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.opentcs.components.plantoverview.PluggablePanel;
import static org.opentcs.guing.plugins.panels.statistics.I18nPlantOverviewPanelStatistics.BUNDLE_PATH;
import org.opentcs.util.statistics.StatisticsLogParser;
import org.opentcs.util.statistics.StatisticsRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A panel for displaying statistics data.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatisticsPanel
    extends PluggablePanel {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StatisticsPanel.class);
  /**
   * This class's resources bundle.
   */
  private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * A file chooser for selecting the input file.
   */
  private final JFileChooser inputFileChooser = new JFileChooser(".");
  /**
   * The input file to be parsed.
   */
  private File inputFile;
  /**
   * The records read from the input file.
   */
  private List<StatisticsRecord> inputRecords;
  /**
   * The parsed analysis data.
   */
  private AnalysisData analysisData;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  /**
   * Creates a new StatisticsPanel.
   */
  public StatisticsPanel() {
    initComponents();

    inputFileChooser.setMultiSelectionEnabled(false);
    inputFileChooser.setFileFilter(new FileNameExtensionFilter(BUNDLE.getString("statisticsPanel.fileChooser_inputFile.fileFilter.description"),
                                                               "txt"));
  }

  @Override
  public void initialize() {
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    initialized = false;
  }

  /**
   * Updates the panel's contents.
   */
  private void updatePanel() {
    if (inputFile == null) {
      analysisInputFileTxt.setText("-");
    }
    else {
      analysisInputFileTxt.setText(inputFile.getAbsolutePath());
    }
    if (inputRecords == null) {
      parsedRecordsTxt.setText("0");
    }
    else {
      parsedRecordsTxt.setText(Integer.toString(inputRecords.size()));
    }
    VehiclesTableModel vehiclesModel = new VehiclesTableModel();
    PointsTableModel pointsModel = new PointsTableModel();
    OrdersTableModel ordersModel = new OrdersTableModel();
    int successfulOrders = 0;
    int lateOrders = 0;
    totalRuntimeTxt.setText("-");
    ordersSuccRateTxt.setText("-");
    ordersDeadlineRateTxt.setText("-");
    if (analysisData != null) {
      totalRuntimeTxt.setText(
          TimePeriodFormat.formatHumanReadable(analysisData.getTotalRuntime()));
      for (VehicleStats vehicle : analysisData.getVehicles()) {
        vehiclesModel.addData(vehicle);
      }
      for (PointStats point : analysisData.getPoints()) {
        pointsModel.addData(point);
      }
      for (OrderStats order : analysisData.getOrders()) {
        ordersModel.addData(order);
        if (order.isFinishedSuccessfully()) {
          successfulOrders++;
        }
        if (order.hasCrossedDeadline()) {
          lateOrders++;
        }
      }

      ordersSuccRateTxt.setText(successfulOrders + "/" + ordersModel.getRowCount());
      ordersDeadlineRateTxt.setText(lateOrders + "/" + ordersModel.getRowCount());
    }
    analysisVehiclesTable.setModel(vehiclesModel);
    analysisCourseTable.setModel(pointsModel);
    analysisOrdersTable.setModel(ordersModel);
  }

  /**
   * Selects and parses an input file.
   */
  private void selectInputFile() {
    int choice = inputFileChooser.showOpenDialog(this);
    if (choice == JFileChooser.APPROVE_OPTION) {
      inputFile = inputFileChooser.getSelectedFile();
      try {
        inputRecords = StatisticsLogParser.parseLog(inputFile);
        analysisData = AnalysisData.analyzeRecords(inputRecords);
        if (analysisData == null) {
          inputFile = null;
          inputRecords = null;
        }
      }
      catch (IOException exc) {
        LOG.warn("Exception parsing input file " + inputFile, exc);
        inputFile = null;
        inputRecords = null;
        analysisData = null;
      }
      updatePanel();
    }
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    jPanel1 = new javax.swing.JPanel();
    analysisInputFileLbl = new javax.swing.JLabel();
    analysisInputFileTxt = new javax.swing.JTextField();
    parsedRecordsLbl = new javax.swing.JLabel();
    parsedRecordsTxt = new javax.swing.JTextField();
    startInputParsingBtn = new javax.swing.JButton();
    totalRuntimeLbl = new javax.swing.JLabel();
    totalRuntimeTxt = new javax.swing.JTextField();
    analysisDataPanel = new javax.swing.JPanel();
    analysisVehiclesPanel = new javax.swing.JPanel();
    jScrollPane1 = new javax.swing.JScrollPane();
    analysisVehiclesTable = new javax.swing.JTable();
    analysisCoursePanel = new javax.swing.JPanel();
    jScrollPane2 = new javax.swing.JScrollPane();
    analysisCourseTable = new javax.swing.JTable();
    analysisOrdersPanel = new javax.swing.JPanel();
    jScrollPane3 = new javax.swing.JScrollPane();
    analysisOrdersTable = new javax.swing.JTable();
    jPanel2 = new javax.swing.JPanel();
    ordersSuccRateLbl = new javax.swing.JLabel();
    ordersSuccRateTxt = new javax.swing.JTextField();
    ordersDeadlineRateLbl = new javax.swing.JLabel();
    ordersDeadlineRateTxt = new javax.swing.JTextField();

    setLayout(new java.awt.BorderLayout());

    jPanel1.setLayout(new java.awt.GridBagLayout());

    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/statisticsPanel/Bundle"); // NOI18N
    analysisInputFileLbl.setText(bundle.getString("statisticsPanel.label_inputFile.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 3);
    jPanel1.add(analysisInputFileLbl, gridBagConstraints);

    analysisInputFileTxt.setEditable(false);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    jPanel1.add(analysisInputFileTxt, gridBagConstraints);

    parsedRecordsLbl.setText(bundle.getString("statisticsPanel.label_parsedRecords.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 3);
    jPanel1.add(parsedRecordsLbl, gridBagConstraints);

    parsedRecordsTxt.setEditable(false);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
    jPanel1.add(parsedRecordsTxt, gridBagConstraints);

    startInputParsingBtn.setText(bundle.getString("statisticsPanel.button_readInputFile.text")); // NOI18N
    startInputParsingBtn.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        startInputParsingBtnActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.gridheight = 3;
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 0, 3);
    jPanel1.add(startInputParsingBtn, gridBagConstraints);

    totalRuntimeLbl.setText(bundle.getString("statisticsPanel.label_totalRuntime.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 3);
    jPanel1.add(totalRuntimeLbl, gridBagConstraints);

    totalRuntimeTxt.setEditable(false);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
    jPanel1.add(totalRuntimeTxt, gridBagConstraints);

    add(jPanel1, java.awt.BorderLayout.NORTH);

    analysisDataPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("statisticsPanel.panel_analysisData.border.title"))); // NOI18N
    analysisDataPanel.setLayout(new javax.swing.BoxLayout(analysisDataPanel, javax.swing.BoxLayout.Y_AXIS));

    analysisVehiclesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("statisticsPanel.panel_analysisVehicles.border.title"))); // NOI18N
    analysisVehiclesPanel.setLayout(new java.awt.BorderLayout());

    jScrollPane1.setPreferredSize(new java.awt.Dimension(550, 200));

    analysisVehiclesTable.setModel(new VehiclesTableModel());
    jScrollPane1.setViewportView(analysisVehiclesTable);

    analysisVehiclesPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);

    analysisDataPanel.add(analysisVehiclesPanel);

    analysisCoursePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("statisticsPanel.panel_analysisCourse.border.title"))); // NOI18N
    analysisCoursePanel.setLayout(new java.awt.BorderLayout());

    jScrollPane2.setPreferredSize(new java.awt.Dimension(550, 200));

    analysisCourseTable.setModel(new PointsTableModel());
    jScrollPane2.setViewportView(analysisCourseTable);

    analysisCoursePanel.add(jScrollPane2, java.awt.BorderLayout.CENTER);

    analysisDataPanel.add(analysisCoursePanel);

    analysisOrdersPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("statisticsPanel.panel_analysisOrders.border.title"))); // NOI18N
    analysisOrdersPanel.setLayout(new java.awt.BorderLayout());

    jScrollPane3.setPreferredSize(new java.awt.Dimension(550, 200));

    analysisOrdersTable.setModel(new OrdersTableModel());
    jScrollPane3.setViewportView(analysisOrdersTable);

    analysisOrdersPanel.add(jScrollPane3, java.awt.BorderLayout.CENTER);

    ordersSuccRateLbl.setText(bundle.getString("statisticsPanel.label_ordersSuccessRate.text")); // NOI18N
    jPanel2.add(ordersSuccRateLbl);

    ordersSuccRateTxt.setEditable(false);
    ordersSuccRateTxt.setColumns(12);
    ordersSuccRateTxt.setText("0");
    jPanel2.add(ordersSuccRateTxt);

    ordersDeadlineRateLbl.setText(bundle.getString("statisticsPanel.label_ordersDeadlineCrossedRate.text")); // NOI18N
    jPanel2.add(ordersDeadlineRateLbl);

    ordersDeadlineRateTxt.setEditable(false);
    ordersDeadlineRateTxt.setColumns(12);
    ordersDeadlineRateTxt.setText("0");
    jPanel2.add(ordersDeadlineRateTxt);

    analysisOrdersPanel.add(jPanel2, java.awt.BorderLayout.SOUTH);

    analysisDataPanel.add(analysisOrdersPanel);

    add(analysisDataPanel, java.awt.BorderLayout.CENTER);

    getAccessibleContext().setAccessibleName(bundle.getString("statisticsPanel.accessibleName")); // NOI18N
  }// </editor-fold>//GEN-END:initComponents

  private void startInputParsingBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startInputParsingBtnActionPerformed
    selectInputFile();
  }//GEN-LAST:event_startInputParsingBtnActionPerformed
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel analysisCoursePanel;
  private javax.swing.JTable analysisCourseTable;
  private javax.swing.JPanel analysisDataPanel;
  private javax.swing.JLabel analysisInputFileLbl;
  private javax.swing.JTextField analysisInputFileTxt;
  private javax.swing.JPanel analysisOrdersPanel;
  private javax.swing.JTable analysisOrdersTable;
  private javax.swing.JPanel analysisVehiclesPanel;
  private javax.swing.JTable analysisVehiclesTable;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JPanel jPanel2;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JScrollPane jScrollPane2;
  private javax.swing.JScrollPane jScrollPane3;
  private javax.swing.JLabel ordersDeadlineRateLbl;
  private javax.swing.JTextField ordersDeadlineRateTxt;
  private javax.swing.JLabel ordersSuccRateLbl;
  private javax.swing.JTextField ordersSuccRateTxt;
  private javax.swing.JLabel parsedRecordsLbl;
  private javax.swing.JTextField parsedRecordsTxt;
  private javax.swing.JButton startInputParsingBtn;
  private javax.swing.JLabel totalRuntimeLbl;
  private javax.swing.JTextField totalRuntimeTxt;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/vehicles/CompositeRechargeVehicleSelectionFilter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.vehicles;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.selection.RechargeVehicleSelectionFilter;

/**
 * A collection of {@link RechargeVehicleSelectionFilter}s.
 * 
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeRechargeVehicleSelectionFilter
    implements RechargeVehicleSelectionFilter {

  /**
   * The {@link RechargeVehicleSelectionFilter}s.
   */
  private final Set<RechargeVehicleSelectionFilter> filters;
  
  @Inject
  public CompositeRechargeVehicleSelectionFilter(Set<RechargeVehicleSelectionFilter> filters) {
    this.filters = requireNonNull(filters, "filters");
  }

  @Override
  public Collection<String> apply(Vehicle vehicle) {
    return filters.stream()
        .flatMap(filter -> filter.apply(vehicle).stream())
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/exchange/AttributeAdapterRegistry.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.guing.exchange.adapter.LocationLockAdapter;
import org.opentcs.guing.exchange.adapter.PathLockAdapter;
import org.opentcs.guing.exchange.adapter.VehicleAllowedOrderTypesAdapter;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Handles registering of model attribute adapters that update a model component's attribute with
 * the kernel when it changes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AttributeAdapterRegistry
    implements EventHandler,
               Lifecycle {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AttributeAdapterRegistry.class);
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * The state of the plant overview.
   */
  private final ApplicationState applicationState;
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The event soruce we're registering with.
   */
  private final EventSource eventSource;
  /**
   * Whether this instance is initialized or not.
   */
  private boolean initialized;

  @Inject
  public AttributeAdapterRegistry(SharedKernelServicePortalProvider portalProvider,
                                  ApplicationState applicationState,
                                  ModelManager modelManager,
                                  @ApplicationEventBus EventSource eventSource) {
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.applicationState = requireNonNull(applicationState, "applicationState");
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.eventSource = requireNonNull(eventSource, "eventSource");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventSource.subscribe(this);
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventSource.unsubscribe(this);
    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof SystemModelTransitionEvent) {
      SystemModelTransitionEvent evt = (SystemModelTransitionEvent) event;
      switch (evt.getStage()) {
        case LOADED:
          registerAdapters();
          break;
        default:
      }
    }
  }

  private void registerAdapters() {
    for (VehicleModel model : modelManager.getModel().getVehicleModels()) {
      model.addAttributesChangeListener(new VehicleAllowedOrderTypesAdapter(portalProvider,
                                                                            applicationState,
                                                                            model));
    }
    for (PathModel model : modelManager.getModel().getPathModels()) {
      model.addAttributesChangeListener(new PathLockAdapter(portalProvider,
                                                            applicationState,
                                                            model));
    }
    for (LocationModel model : modelManager.getModel().getLocationModels()) {
      model.addAttributesChangeListener(new LocationLockAdapter(portalProvider,
                                                                applicationState,
                                                                model));
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/PeripheralInformation.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.Serializable;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * Contains details about a peripheral device a location may represent.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralInformation
    implements Serializable {

  /**
   * A token for which a location/peripheral device is currently reserved.
   */
  @Nullable
  private final String reservationToken;
  /**
   * This peripheral device's current state.
   */
  @Nonnull
  private final State state;
  /**
   * This peripheral device's current processing state.
   */
  @Nonnull
  private final ProcState procState;
  /**
   * A reference to the peripheral job this peripheral device is currently processing.
   */
  @Nullable
  private final TCSObjectReference<PeripheralJob> peripheralJob;

  public PeripheralInformation() {
    this(null, State.NO_PERIPHERAL, ProcState.IDLE, null);
  }

  private PeripheralInformation(
      @Nullable String reservationToken,
      @Nonnull State state,
      @Nonnull ProcState procState,
      @Nullable TCSObjectReference<PeripheralJob> peripheralJob) {
    this.reservationToken = reservationToken;
    this.state = Objects.requireNonNull(state, "state");
    this.procState = Objects.requireNonNull(procState, "procState");
    this.peripheralJob = peripheralJob;
  }

  /**
   * Returns a token for which a location/peripheral device is currently reserved.
   *
   * @return A token for which a location/peripheral device is currently reserved.
   */
  @Nullable
  public String getReservationToken() {
    return reservationToken;
  }

  /**
   * Creates a copy of this object, with the given reservation token.
   *
   * @param reservationToken The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralInformation withReservationToken(@Nullable String reservationToken) {
    return new PeripheralInformation(reservationToken, state, procState, peripheralJob);
  }

  /**
   * Returns the peripheral device's current state.
   *
   * @return The peripheral device's current state.
   */
  @Nonnull
  public State getState() {
    return state;
  }

  /**
   * Creates a copy of this object, with the given state.
   *
   * @param state The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralInformation withState(@Nonnull State state) {
    return new PeripheralInformation(reservationToken, state, procState, peripheralJob);
  }

  /**
   * Returns the peripheral device's current processing state.
   *
   * @return The peripheral device's current processing state.
   */
  @Nonnull
  public ProcState getProcState() {
    return procState;
  }

  /**
   * Creates a copy of this object, with the given processing state.
   *
   * @param procState The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralInformation withProcState(@Nonnull ProcState procState) {
    return new PeripheralInformation(reservationToken, state, procState, peripheralJob);
  }

  /**
   * Returns a reference to the peripheral job this peripheral device is currently processing.
   *
   * @return A reference to the peripheral job this peripheral device is currently processing,
   * or {@code null}, it is not processing any peripheral job at the moment.
   */
  @Nullable
  public TCSObjectReference<PeripheralJob> getPeripheralJob() {
    return peripheralJob;
  }

  /**
   * Creates a copy of this object, with the given peripheral job.
   *
   * @param peripheralJob The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralInformation withPeripheralJob(
      @Nullable TCSObjectReference<PeripheralJob> peripheralJob) {
    return new PeripheralInformation(reservationToken, state, procState, peripheralJob);
  }

  /**
   * The elements of this enumeration describe the various possible states of a peripheral device.
   */
  public enum State {
    /**
     * Indicates that the location the {@link PeripheralInformation} belongs to doesn't represent
     * a peripheral device.
     */
    NO_PERIPHERAL,
    /**
     * The peripheral device's current state is unknown, e.g. because communication with
     * it is currently not possible for some reason.
     */
    UNKNOWN,
    /**
     * The peripheral device's state is known and it's not in an error state, but it is
     * not available for receiving jobs.
     */
    UNAVAILABLE,
    /**
     * There is a problem with the peripheral device.
     */
    ERROR,
    /**
     * The peripheral device is currently idle/available for processing jobs.
     */
    IDLE,
    /**
     * The peripheral device is processing a job.
     */
    EXECUTING
  }

  /**
   * A peripheral device's processing state as seen by the peripheral job dispatcher.
   */
  public enum ProcState {
    /**
     * The peripheral device is currently not processing a job.
     */
    IDLE,
    /**
     * The peripheral device is currently processing a job.
     */
    PROCESSING_JOB
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/action/ActionFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action;

import java.util.Collection;
import org.opentcs.data.model.Vehicle;
import org.opentcs.guing.application.action.course.FollowVehicleAction;
import org.opentcs.guing.application.action.course.IntegrationLevelChangeAction;
import org.opentcs.guing.application.action.course.ScrollToVehicleAction;
import org.opentcs.guing.application.action.course.SendVehicleToLocationAction;
import org.opentcs.guing.application.action.course.SendVehicleToPointAction;
import org.opentcs.guing.application.action.course.WithdrawAction;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 * A factory for various actions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ActionFactory {

  ScrollToVehicleAction createScrollToVehicleAction(VehicleModel vehicleModel);

  FollowVehicleAction createFollowVehicleAction(VehicleModel vehicleModel);

  SendVehicleToPointAction createSendVehicleToPointAction(VehicleModel vehicleModel);

  SendVehicleToLocationAction createSendVehicleToLocationAction(VehicleModel vehicleModel);

  WithdrawAction createWithdrawAction(Collection<VehicleModel> vehicles, boolean immediateAbort);

  IntegrationLevelChangeAction createIntegrationLevelChangeAction(Collection<VehicleModel> vehicles,
                                                                  Vehicle.IntegrationLevel level);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/vehicle/VehicleComparatorByName.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.vehicle;

import java.util.Comparator;
import org.opentcs.data.model.Vehicle;

/**
 * Compares {@link Vehicle}s by their names.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleComparatorByName
    implements Comparator<Vehicle> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "BY_NAME";

  @Override
  public int compare(Vehicle vehicle1, Vehicle vehicle2) {
    return vehicle1.getName().compareTo(vehicle2.getName());
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/order/package-info.java<|end_filename|>
/**
 * Transfer object classes for transport order objects.
 */
package org.opentcs.access.to.order;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/VehicleFilterResult.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import org.opentcs.data.model.Vehicle;

/**
 * The result of a vehicle filter operation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleFilterResult {

  private final Vehicle vehicle;

  private final Collection<String> filterReasons;

  public VehicleFilterResult(Vehicle vehicle, Collection<String> filterReasons) {
    this.vehicle = requireNonNull(vehicle, "vehicle");
    this.filterReasons = requireNonNull(filterReasons, "filterReasons");
  }

  public Vehicle getVehicle() {
    return vehicle;
  }

  public Collection<String> getFilterReasons() {
    return filterReasons;
  }

  public boolean isFiltered() {
    return !filterReasons.isEmpty();
  }
}


<|start_filename|>openTCS-ModelEditor/src/guiceConfig/java/org/opentcs/guing/application/toolbar/ToolBarInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.toolbar;

import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import javax.inject.Singleton;
import org.jhotdraw.draw.tool.DragTracker;
import org.jhotdraw.draw.tool.SelectAreaTracker;
import org.opentcs.guing.application.action.ToolBarManager;
import org.opentcs.thirdparty.jhotdraw.application.toolbar.OpenTCSDragTracker;
import org.opentcs.thirdparty.jhotdraw.application.toolbar.OpenTCSSelectAreaTracker;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ToolBarInjectionModule
    extends AbstractModule {

  @Override
  protected void configure() {
    install(new FactoryModuleBuilder().build(SelectionToolFactory.class));
    install(new FactoryModuleBuilder().build(CreationToolFactory.class));
    
    bind(ToolBarManager.class).in(Singleton.class);

    bind(SelectAreaTracker.class).to(OpenTCSSelectAreaTracker.class);
    bind(DragTracker.class).to(OpenTCSDragTracker.class);
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/PeripheralJobDispatcher.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Location;

/**
 * This interface declares the methods a peripheral job dispatcher module for the openTCS kernel 
 * must implement.
 * <p>
 * A peripheral job dispatcher manages the distribution of peripheral jobs among the perihperal 
 * devices represented by locations in a system. It is basically event-driven, where an event can 
 * be a new peripheral job being introduced into the system or a peripheral device becoming
 * available for processing existing jobs.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralJobDispatcher
    extends Lifecycle {

  /**
   * Notifies the dispatcher that it should start the dispatching process.
   */
  void dispatch();

  /**
   * Notifies the dispatcher that any job a peripheral device (represented by the given location)
   * might be processing is to be withdrawn.
   *
   * @param location The location representing a peripheral device whose job is withdrawn.
   */
  void withdrawJob(@Nonnull Location location);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/ModelLayoutElementCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.Map;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * A transfer object describing a model layout element in the visual layout.
 *
 * @author <NAME> (Fraunhofer IML)
 * @deprecated Will be removed in favor of dedicated layout classes in corresponding TCS data
 * objects.
 */
@Deprecated
@ScheduledApiChange(details = "Will be removed.", when = "6.0")
public class ModelLayoutElementCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The layer on which this model layout element is to be displayed.
   */
  private int layer;

  /**
   * Creates a new instance.
   *
   * @param name The name of this model layout element.
   */
  public ModelLayoutElementCreationTO(String name) {
    super(name);
  }

  private ModelLayoutElementCreationTO(@Nonnull String name,
                                       @Nonnull Map<String, String> properties,
                                       int layer) {
    super(name, properties);
    this.layer = layer;
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new name.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public ModelLayoutElementCreationTO withName(@Nonnull String name) {
    return new ModelLayoutElementCreationTO(name, getModifiableProperties(), layer);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public ModelLayoutElementCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new ModelLayoutElementCreationTO(getName(), properties, layer);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public ModelLayoutElementCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new ModelLayoutElementCreationTO(getName(), propertiesWith(key, value), layer);
  }

  /**
   * Returns the layer on which this model layout element is to be displayed.
   *
   * @return The layer on which this model layout element is to be displayed.
   */
  public int getLayer() {
    return layer;
  }

  /**
   * Creates a copy of this object with the given layer on which this model layout element is to be displayed.
   *
   * @param layer The new layer
   * @return A copy of this object, differing in the given layer.
   */
  public ModelLayoutElementCreationTO withLayer(int layer) {
    return new ModelLayoutElementCreationTO(getName(), getModifiableProperties(), layer);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteRouterServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;

/**
 * The default implementation of the router service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemoteRouterServiceProxy
    extends AbstractRemoteServiceProxy<RemoteRouterService>
    implements RouterService {

  @Override
  public void updatePathLock(TCSObjectReference<Path> ref, boolean locked)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().updatePathLock(getClientId(), ref, locked);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void updateRoutingTopology()
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().updateRoutingTopology(getClientId());
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/CurrentMovementCommandFailedCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.MovementCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;

/**
 * A command to notify the loopback adapter the last/current movement command failed.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CurrentMovementCommandFailedCommand
    implements AdapterCommand {

  @Override
  public void execute(VehicleCommAdapter adapter) {
    MovementCommand failedCommand = adapter.getSentQueue().peek();
    if (failedCommand != null) {
      adapter.getProcessModel().commandFailed(adapter.getSentQueue().peek());
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardTransportOrderService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.TCSObjectPool;
import org.opentcs.kernel.workingset.TransportOrderPool;

/**
 * This class is the standard implementation of the {@link TransportOrderService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardTransportOrderService
    extends AbstractTCSObjectService
    implements InternalTransportOrderService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The container of all course model and transport order objects.
   */
  private final TCSObjectPool globalObjectPool;
  /**
   * The order facade to the object pool.
   */
  private final TransportOrderPool orderPool;
  /**
   * The model facade to the object pool.
   */
  private final Model model;

  /**
   * Creates a new instance.
   *
   * @param objectService The tcs obejct service.
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param globalObjectPool The object pool to be used.
   * @param orderPool The oder pool to be used.
   * @param model The model to be used.
   */
  @Inject
  public StandardTransportOrderService(TCSObjectService objectService,
                                       @GlobalSyncObject Object globalSyncObject,
                                       TCSObjectPool globalObjectPool,
                                       TransportOrderPool orderPool,
                                       Model model) {
    super(objectService);
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.globalObjectPool = requireNonNull(globalObjectPool, "globalObjectPool");
    this.orderPool = requireNonNull(orderPool, "orderPool");
    this.model = requireNonNull(model, "model");
  }

  @Override
  public void markOrderSequenceFinished(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      OrderSequence seq = globalObjectPool.getObject(OrderSequence.class, ref);
      // Make sure we don't execute this if the sequence is already marked as finished, as that
      // would make it possible to trigger disposition of a vehicle at any given moment.
      if (seq.isFinished()) {
        return;
      }

      orderPool.setOrderSequenceFinished(ref);
      // If the sequence was being processed by a vehicle, clear its back reference to the sequence
      // to make it available again and dispatch it.
      if (seq.getProcessingVehicle() != null) {
        Vehicle vehicle = globalObjectPool.getObject(Vehicle.class,
                                                     seq.getProcessingVehicle());
        model.setVehicleOrderSequence(vehicle.getReference(), null);
      }
    }
  }

  @Override
  public void updateOrderSequenceFinishedIndex(TCSObjectReference<OrderSequence> ref, int index)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      orderPool.setOrderSequenceFinishedIndex(ref, index);
    }
  }

  @Override
  public void updateOrderSequenceProcessingVehicle(TCSObjectReference<OrderSequence> seqRef,
                                                   TCSObjectReference<Vehicle> vehicleRef)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      orderPool.setOrderSequenceProcessingVehicle(seqRef, vehicleRef);
    }
  }

  @Override
  public void updateTransportOrderProcessingVehicle(TCSObjectReference<TransportOrder> orderRef,
                                                    TCSObjectReference<Vehicle> vehicleRef,
                                                    List<DriveOrder> driveOrders)
      throws ObjectUnknownException, IllegalArgumentException {
    synchronized (globalSyncObject) {
      orderPool.setTransportOrderProcessingVehicle(orderRef, vehicleRef, driveOrders);
    }
  }

  @Override
  public void updateTransportOrderDriveOrders(TCSObjectReference<TransportOrder> ref,
                                              List<DriveOrder> driveOrders)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      orderPool.setTransportOrderDriveOrders(ref, driveOrders);
    }
  }

  @Override
  public void updateTransportOrderNextDriveOrder(TCSObjectReference<TransportOrder> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      orderPool.setTransportOrderNextDriveOrder(ref);
    }
  }

  @Override
  public void updateTransportOrderState(TCSObjectReference<TransportOrder> ref,
                                        TransportOrder.State state)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      orderPool.setTransportOrderState(ref, state);
    }
  }

  @Override
  public OrderSequence createOrderSequence(OrderSequenceCreationTO to) {
    synchronized (globalSyncObject) {
      return orderPool.createOrderSequence(to);
    }
  }

  @Override
  public TransportOrder createTransportOrder(TransportOrderCreationTO to)
      throws ObjectUnknownException, ObjectExistsException {
    synchronized (globalSyncObject) {
      return orderPool.createTransportOrder(to);
    }
  }

  @Override
  public void markOrderSequenceComplete(TCSObjectReference<OrderSequence> ref)
      throws ObjectUnknownException {
    synchronized (globalSyncObject) {
      OrderSequence seq = globalObjectPool.getObject(OrderSequence.class, ref);
      // Make sure we don't execute this if the sequence is already marked as finished, as that
      // would make it possible to trigger disposition of a vehicle at any given moment.
      if (seq.isComplete()) {
        return;
      }
      orderPool.setOrderSequenceComplete(ref);
      // If there aren't any transport orders left to be processed as part of the sequence, mark
      // it as finished, too.
      if (seq.getNextUnfinishedOrder() == null) {
        orderPool.setOrderSequenceFinished(ref);
        // If the sequence was being processed by a vehicle, clear its back reference to the
        // sequence to make it available again and dispatch it.
        if (seq.getProcessingVehicle() != null) {
          Vehicle vehicle = globalObjectPool.getObject(Vehicle.class,
                                                       seq.getProcessingVehicle());
          model.setVehicleOrderSequence(vehicle.getReference(), null);
        }
      }
    }
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/PeriodicPeripheralRedispatchingTask.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Periodically checks for idle peripheral devices that could process a peripheral job.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeriodicPeripheralRedispatchingTask
    implements Runnable {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeriodicPeripheralRedispatchingTask.class);

  private final PeripheralDispatcherService dispatcherService;

  private final TCSObjectService objectService;

  /**
   * Creates a new instance.
   *
   * @param dispatcherService The dispatcher service used to dispatch peripheral devices.
   * @param objectService The object service.
   */
  @Inject
  public PeriodicPeripheralRedispatchingTask(PeripheralDispatcherService dispatcherService,
                                             TCSObjectService objectService) {
    this.dispatcherService = requireNonNull(dispatcherService, "dispatcherService");
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public void run() {
    // If there are any peripheral devices that could process a peripheral job,
    // trigger the dispatcher once.
    objectService.fetchObjects(Location.class, this::couldProcessJob).stream()
        .findAny()
        .ifPresent(location -> {
          LOG.debug("Peripheral {} could process peripheral job, triggering dispatcher ...",
                    location);
          dispatcherService.dispatch();
        });
  }

  private boolean couldProcessJob(Location location) {
    return location.getPeripheralInformation().getState() != PeripheralInformation.State.NO_PERIPHERAL
        && (processesNoJob(location));
  }

  private boolean processesNoJob(Location location) {
    return location.getPeripheralInformation().getProcState()
        == PeripheralInformation.ProcState.IDLE
        && location.getPeripheralInformation().getState()
        == PeripheralInformation.State.IDLE;
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/SetSingleStepModeEnabledCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.virtualvehicle.LoopbackCommunicationAdapter;

/**
 * A command to enable/disable the comm adapter's single step mode.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetSingleStepModeEnabledCommand
    implements AdapterCommand {

  /**
   * Whether to enable/disable single step mode.
   */
  private final boolean enabled;

  /**
   * Creates a new instance.
   *
   * @param enabled Whether to enable/disable single step mode.
   */
  public SetSingleStepModeEnabledCommand(boolean enabled) {
    this.enabled = enabled;
  }

  @Override
  public void execute(VehicleCommAdapter adapter) {
    if (!(adapter instanceof LoopbackCommunicationAdapter)) {
      return;
    }

    LoopbackCommunicationAdapter loopbackAdapter = (LoopbackCommunicationAdapter) adapter;
    loopbackAdapter.getProcessModel().setSingleStepModeEnabled(enabled);
  }

}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/menubar/FileMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.action.file.DownloadModelFromKernelAction;
import org.opentcs.guing.application.action.file.LoadModelAction;
import org.opentcs.guing.application.action.file.ModelPropertiesAction;
import org.opentcs.guing.application.action.file.NewModelAction;
import org.opentcs.guing.application.action.file.SaveModelAction;
import org.opentcs.guing.application.action.file.SaveModelAsAction;
import org.opentcs.guing.application.action.file.UploadModelToKernelAction;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.application.action.file.CloseFileAction;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's "File" menu.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FileMenu
    extends JMenu {

  /**
   * A menu item for creating a new, empty system model.
   */
  private final JMenuItem menuItemNewModel;
  /**
   * A menu item for loading a mode into the kernel.
   */
  private final JMenuItem menuItemLoadModel;
  /**
   * A menu item for saving the kernel's current model.
   */
  private final JMenuItem menuItemSaveModel;
  /**
   * A menu item for saving the kernel's current model with a new name.
   */
  private final JMenuItem menuItemSaveModelAs;
  /**
   * A menu item for retrieving the system model data from the kernel.
   */
  private final JMenuItem menuItemDownloadModelFromKernel;
  /**
   * A menu item for transferring the system model data to the kernel.
   */
  private final JMenuItem menuItemUploadModelToKernel;
  /**
   * A menu item for showing the current model's properties.
   */
  private final JMenuItem menuItemModelProperties;
  /**
   * A menu item for closing the application.
   */
  private final JMenuItem menuItemClose;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   * @param menuImport The sub-menu for the selectable plant model importers.
   * @param menuExport The sub-menu for the selectable plant model exporters.
   */
  @Inject
  public FileMenu(ViewActionMap actionMap,
                  FileImportMenu menuImport,
                  FileExportMenu menuExport) {
    requireNonNull(actionMap, "actionMap");
    requireNonNull(menuImport, "menuImport");
    requireNonNull(menuExport, "menuExport");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);

    this.setText(labels.getString("fileMenu.text"));
    this.setToolTipText(labels.getString("fileMenu.tooltipText"));
    this.setMnemonic('F');

    // Menu item File -> New Model
    menuItemNewModel = new JMenuItem(actionMap.get(NewModelAction.ID));
    add(menuItemNewModel);

    // Menu item File -> Load Model
    menuItemLoadModel = new JMenuItem(actionMap.get(LoadModelAction.ID));
    add(menuItemLoadModel);

    // Menu item File -> Save Model
    menuItemSaveModel = new JMenuItem(actionMap.get(SaveModelAction.ID));
    add(menuItemSaveModel);

    // Menu item File -> Save Model As
    menuItemSaveModelAs = new JMenuItem(actionMap.get(SaveModelAsAction.ID));
    add(menuItemSaveModelAs);

    addSeparator();

    add(menuImport);
    add(menuExport);

    addSeparator();

    // Load model from kernel
    menuItemDownloadModelFromKernel = new JMenuItem(actionMap.get(DownloadModelFromKernelAction.ID));
    add(menuItemDownloadModelFromKernel);

    // Persist model in kernel
    menuItemUploadModelToKernel = new JMenuItem(actionMap.get(UploadModelToKernelAction.ID));
    add(menuItemUploadModelToKernel);

    addSeparator();

    menuItemModelProperties = new JMenuItem(actionMap.get(ModelPropertiesAction.ID));
    add(menuItemModelProperties);

    addSeparator();

    // Menu item File -> Close
    menuItemClose = new JMenuItem(actionMap.get(CloseFileAction.ID));
    add(menuItemClose);
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/orders/CompositeTransportOrderSelectionFilter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.orders;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.selection.TransportOrderSelectionFilter;

/**
 * A collection of {@link TransportOrderSelectionFilter}s.
 * 
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeTransportOrderSelectionFilter
    implements TransportOrderSelectionFilter {

  /**
   * The {@link TransportOrderSelectionFilter}s.
   */
  private final Set<TransportOrderSelectionFilter> filters;
  
  @Inject
  public CompositeTransportOrderSelectionFilter(Set<TransportOrderSelectionFilter> filters) {
    this.filters = requireNonNull(filters, "filters");
  }

  @Override
  public Collection<String> apply(TransportOrder order) {
    return filters.stream()
        .flatMap(filter -> filter.apply(order).stream())
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-ResourceAllocation/src/main/java/org/opentcs/guing/plugins/panels/allocation/AllocationTreeModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.allocation;

import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import org.opentcs.data.model.TCSResourceReference;
import static org.opentcs.guing.plugins.panels.allocation.I18nPlantOverviewPanelResourceAllocation.BUNDLE_PATH;

/**
 * A model for a resource allocation tree to display an alphabetically ordered view for vehicle
 * names and their not ordered allocated resources.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AllocationTreeModel
    extends DefaultTreeModel {

  /**
   * This class' bundle.
   */
  private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_PATH);

  /**
   * Creates a new instance.
   */
  public AllocationTreeModel() {
    super(new DefaultMutableTreeNode(BUNDLE.getString("resourceAllocationPanel.treeRoot.text")),
          true);
  }

  /**
   * Updates the vehicle resource allocations displayed in this tree model.
   *
   * @param vehicleName The name of the vehicle
   * @param newAllocations The new vehicle resource allocations
   */
  public void updateAllocations(String vehicleName, List<TCSResourceReference<?>> newAllocations) {
    updateVehicleAllocation(vehicleName, newAllocations);
    removeNotAllocatedVehicles(vehicleName, newAllocations);
  }

  /**
   * Removes all vehicle tree nodes where the vehicle does not have any resources allocated.
   *
   * @param allocatedVehicles The vehicles which have a resource allocation
   */
  private void removeNotAllocatedVehicles(String vehicleName,
                                          List<TCSResourceReference<?>> resources) {
    @SuppressWarnings("unchecked")
    List<DefaultMutableTreeNode> rootChildren
        = Collections.list((Enumeration<DefaultMutableTreeNode>) root.children());

    for (DefaultMutableTreeNode currentNode : rootChildren) {
      Object userObject = currentNode.getUserObject();
      //If we have a vehicle node but the vehicle name is not in the set, remove it
      if (userObject.equals(vehicleName) && resources.isEmpty()) {
        removeNodeFromParent(currentNode);
      }
    }
  }

  /**
   * Updates the allocated resources for a specified vehicle if necessarry.
   *
   * @param vehicleName The name of the vehicle
   * @param resources The allocated resources of the vehicle
   */
  private void updateVehicleAllocation(String vehicleName, List<TCSResourceReference<?>> resources) {
    DefaultMutableTreeNode vehicleNode = null;
    for (int x = 0; x < root.getChildCount(); x++) {
      DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) root.getChildAt(x);
      if (currentNode.getUserObject().equals(vehicleName)) {
        vehicleNode = currentNode;
      }
    }
    if (vehicleNode == null) {
      vehicleNode = createNewVehicleNode(vehicleName);
    }
    //Remove all children that are not in the new allocation
    List<DefaultMutableTreeNode> vehicleChildren = Collections.list(vehicleNode.children()).stream()
        .map(treeNode -> (DefaultMutableTreeNode) treeNode)
        .collect(Collectors.toList());
    for (DefaultMutableTreeNode current : vehicleChildren) {
      if (!resources.contains((TCSResourceReference<?>) current.getUserObject())) {
        vehicleNode.remove(current);
      }
    }
    //Add new resources that are not in the jtree already at the correct position
    int index = 0;
    for (TCSResourceReference<?> resource : resources) {
      if (vehicleNode.getChildCount() <= index) {
        //Insert the resource at this position
        vehicleNode.insert(new DefaultMutableTreeNode(resource, false), index);
      }
      else {
        DefaultMutableTreeNode current = (DefaultMutableTreeNode) vehicleNode.getChildAt(index);
        TCSResourceReference<?> resource2 = (TCSResourceReference<?>) current.getUserObject();
        //Check if the resource exists at the current position - then we dont have to do anything
        if (!resource.equals(resource2)) {
          //Check if the resource exists at another position in the children list
          int existIndex = getChildIndexOf(resource, vehicleNode);
          //If the resource already exists at another point, move it to the index
          if (existIndex > 0) {
            vehicleNode.remove(existIndex);
          }
          //Insert the resource at this position
          vehicleNode.insert(new DefaultMutableTreeNode(resource, false), index);
        }
      }
      index++;
    }

    reload(vehicleNode);
  }

  /**
   * Returns the index of the first children containing the resource as user object.
   *
   * @param resource The resource to search for
   * @param vehicleNode The parent node
   * @return The index of the node containing the resource or -1 if not found
   */
  private int getChildIndexOf(TCSResourceReference<?> resource, DefaultMutableTreeNode vehicleNode) {
    int index = 0;

    List<DefaultMutableTreeNode> vehicleChildren = Collections.list(vehicleNode.children()).stream()
        .map(treeNode -> (DefaultMutableTreeNode) treeNode)
        .collect(Collectors.toList());

    for (DefaultMutableTreeNode child : vehicleChildren) {
      if (child.getUserObject().equals(resource)) {
        return index;
      }
      index++;
    }
    return -1;
  }

  /**
   * Creates a new vehicle node and adds it to the root node in alphabetical order.
   *
   * @param vehicleName The name of the vehicle and the user object of the new vehicle node
   * @return The vehicle node
   */
  private DefaultMutableTreeNode createNewVehicleNode(String vehicleName) {
    boolean inserted = false;
    DefaultMutableTreeNode vehicleNode = new DefaultMutableTreeNode(vehicleName);
    for (int x = 0; x < root.getChildCount(); x++) {
      DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) root.getChildAt(x);
      //Insert node alphabetically
      if (!inserted && vehicleName.compareTo((String) currentNode.getUserObject()) <= 0) {
        insertNodeInto(vehicleNode, (MutableTreeNode) root, x);
        inserted = true;
      }
    }
    if (!inserted) {
      insertNodeInto(vehicleNode, (MutableTreeNode) root, root.getChildCount());
    }
    return vehicleNode;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/guiceConfig/java/org/opentcs/strategies/basic/dispatching/DefaultDispatcherModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
import java.util.Comparator;
import javax.inject.Singleton;
import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.phase.parking.DefaultParkingPositionSupplier;
import org.opentcs.strategies.basic.dispatching.phase.parking.ParkingPositionSupplier;
import org.opentcs.strategies.basic.dispatching.phase.recharging.DefaultRechargePositionSupplier;
import org.opentcs.strategies.basic.dispatching.phase.recharging.RechargePositionSupplier;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeOrderCandidateComparator;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeOrderComparator;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeVehicleCandidateComparator;
import org.opentcs.strategies.basic.dispatching.priorization.CompositeVehicleComparator;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByCompleteRoutingCosts;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByDeadline;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByEnergyLevel;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByInitialRoutingCosts;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByOrderAge;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByOrderName;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByVehicleName;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorIdleFirst;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorByAge;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorByDeadline;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorByName;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorByEnergyLevel;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorByName;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorIdleFirst;
import org.opentcs.strategies.basic.dispatching.selection.AssignmentCandidateSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.ParkVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.RechargeVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.ReparkVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.TransportOrderSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.VehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.candidates.IsProcessable;
import org.opentcs.strategies.basic.dispatching.selection.orders.CompositeTransportOrderSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.orders.ContainsLockedTargetLocations;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeParkVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeRechargeVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeReparkVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeVehicleSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.IsIdleAndDegraded;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.IsParkable;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.IsReparkable;

/**
 * Guice configuration for the default dispatcher.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultDispatcherModule
    extends KernelInjectionModule {

  @Override
  protected void configure() {
    configureDispatcherDependencies();
    bindDispatcher(DefaultDispatcher.class);
  }

  private void configureDispatcherDependencies() {
    Multibinder.newSetBinder(binder(), VehicleSelectionFilter.class);
    Multibinder.newSetBinder(binder(), TransportOrderSelectionFilter.class)
        .addBinding().to(ContainsLockedTargetLocations.class);
    Multibinder.newSetBinder(binder(), ParkVehicleSelectionFilter.class)
        .addBinding().to(IsParkable.class);
    Multibinder.newSetBinder(binder(), ReparkVehicleSelectionFilter.class)
        .addBinding().to(IsReparkable.class);
    Multibinder.newSetBinder(binder(), RechargeVehicleSelectionFilter.class)
        .addBinding().to(IsIdleAndDegraded.class);
    Multibinder.newSetBinder(binder(), AssignmentCandidateSelectionFilter.class)
        .addBinding().to(IsProcessable.class);

    bind(CompositeParkVehicleSelectionFilter.class)
        .in(Singleton.class);
    bind(CompositeReparkVehicleSelectionFilter.class)
        .in(Singleton.class);
    bind(CompositeRechargeVehicleSelectionFilter.class)
        .in(Singleton.class);
    bind(CompositeTransportOrderSelectionFilter.class)
        .in(Singleton.class);
    bind(CompositeVehicleSelectionFilter.class)
        .in(Singleton.class);
    bind(CompositeAssignmentCandidateSelectionFilter.class)
        .in(Singleton.class);

    bind(DefaultDispatcherConfiguration.class)
        .toInstance(getConfigBindingProvider().get(DefaultDispatcherConfiguration.PREFIX,
                                                   DefaultDispatcherConfiguration.class));

    bind(OrderReservationPool.class)
        .in(Singleton.class);

    bind(ParkingPositionSupplier.class)
        .to(DefaultParkingPositionSupplier.class)
        .in(Singleton.class);
    bind(RechargePositionSupplier.class)
        .to(DefaultRechargePositionSupplier.class)
        .in(Singleton.class);

    MapBinder<String, Comparator<Vehicle>> vehicleComparatorBinder
        = MapBinder.newMapBinder(binder(),
                                 new TypeLiteral<String>() {
                             },
                                 new TypeLiteral<Comparator<Vehicle>>() {
                             });
    vehicleComparatorBinder
        .addBinding(VehicleComparatorByEnergyLevel.CONFIGURATION_KEY)
        .to(VehicleComparatorByEnergyLevel.class);
    vehicleComparatorBinder
        .addBinding(VehicleComparatorByName.CONFIGURATION_KEY)
        .to(VehicleComparatorByName.class);
    vehicleComparatorBinder
        .addBinding(VehicleComparatorIdleFirst.CONFIGURATION_KEY)
        .to(VehicleComparatorIdleFirst.class);

    MapBinder<String, Comparator<TransportOrder>> orderComparatorBinder
        = MapBinder.newMapBinder(binder(),
                                 new TypeLiteral<String>() {
                             },
                                 new TypeLiteral<Comparator<TransportOrder>>() {
                             });
    orderComparatorBinder
        .addBinding(TransportOrderComparatorByAge.CONFIGURATION_KEY)
        .to(TransportOrderComparatorByAge.class);
    orderComparatorBinder
        .addBinding(TransportOrderComparatorByDeadline.CONFIGURATION_KEY)
        .to(TransportOrderComparatorByDeadline.class);
    orderComparatorBinder
        .addBinding(TransportOrderComparatorByName.CONFIGURATION_KEY)
        .to(TransportOrderComparatorByName.class);

    MapBinder<String, Comparator<AssignmentCandidate>> candidateComparatorBinder
        = MapBinder.newMapBinder(binder(),
                                 new TypeLiteral<String>() {
                             },
                                 new TypeLiteral<Comparator<AssignmentCandidate>>() {
                             });
    candidateComparatorBinder
        .addBinding(CandidateComparatorByCompleteRoutingCosts.CONFIGURATION_KEY)
        .to(CandidateComparatorByCompleteRoutingCosts.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorByDeadline.CONFIGURATION_KEY)
        .to(CandidateComparatorByDeadline.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorByEnergyLevel.CONFIGURATION_KEY)
        .to(CandidateComparatorByEnergyLevel.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorByInitialRoutingCosts.CONFIGURATION_KEY)
        .to(CandidateComparatorByInitialRoutingCosts.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorByOrderAge.CONFIGURATION_KEY)
        .to(CandidateComparatorByOrderAge.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorByOrderName.CONFIGURATION_KEY)
        .to(CandidateComparatorByOrderName.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorByVehicleName.CONFIGURATION_KEY)
        .to(CandidateComparatorByVehicleName.class);
    candidateComparatorBinder
        .addBinding(CandidateComparatorIdleFirst.CONFIGURATION_KEY)
        .to(CandidateComparatorIdleFirst.class);

    bind(CompositeVehicleComparator.class)
        .in(Singleton.class);
    bind(CompositeOrderComparator.class)
        .in(Singleton.class);
    bind(CompositeOrderCandidateComparator.class)
        .in(Singleton.class);
    bind(CompositeVehicleCandidateComparator.class)
        .in(Singleton.class);

    bind(TransportOrderUtil.class)
        .in(Singleton.class);
  }

}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/SimpleFolder.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

/**
 * The simplest form of a component in the system model that contains child elements.
 * SimpleFolder is used for plain folders.
 * 
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class SimpleFolder
    extends CompositeModelComponent {

  /**
   * Creates a new instance.
   *
   * @param name The name of the folder.
   */
  public SimpleFolder(String name) {
    super(name);
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/Relation.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.io.Serializable;

/**
 * A conversion relationship between two units.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class Relation<U>
    implements Serializable {

  /**
   * The source unit.
   */
  private final U fUnitFrom;
  /**
   * The destination unit.
   */
  private final U fUnitTo;
  /**
   * The conversion relationship.
   */
  private final double fRelationValue;

  /**
   * Creates a new instance.
   *
   * @param unitFrom The unit from which to convert.
   * @param unitTo The unit to which to convert.
   * @param relationValue The relation value between the two units.
   */
  public Relation(U unitFrom, U unitTo, double relationValue) {
    fUnitFrom = unitFrom;
    fUnitTo = unitTo;
    fRelationValue = relationValue;
  }

  /**
   * Checks if this relation is applicable to the specified units.
   *
   * @param unitA The first unit.
   * @param unitB The second unit.
   * @return {@code true}, if the two given units are covered by this relation, otherwise
   * {@code false}.
   */
  public boolean fits(U unitA, U unitB) {
    if (fUnitFrom.equals(unitA) && fUnitTo.equals(unitB)) {
      return true;
    }

    if (fUnitFrom.equals(unitB) && fUnitTo.equals(unitA)) {
      return true;
    }

    return false;
  }

  /**
   * Returns the conversion relationship as a number.
   *
   * @return The relation value between the two units. 
   */
  public double relationValue() {
    return fRelationValue;
  }

  /**
   * Returns the operation used for the conversion of the first unit into the second unit.
   *
   * @param unitFrom The unit from which to convert.
   * @param unitTo The unit to which to convert.
   * @return The operation that is to be used for the conversion.
   */
  public Operation getOperation(U unitFrom, U unitTo) {
    if (unitFrom.equals(fUnitFrom)) {
      return Operation.DIVISION;
    }
    else {
      return Operation.MULTIPLICATION;
    }
  }

  public static enum Operation {
    DIVISION,
    MULTIPLICATION
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteNotificationServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import java.util.List;
import java.util.function.Predicate;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.data.notification.UserNotification;

/**
 * The default implementation of the notification service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemoteNotificationServiceProxy
    extends AbstractRemoteServiceProxy<RemoteNotificationService>
    implements NotificationService {

  @Override
  public List<UserNotification> fetchUserNotifications(Predicate<UserNotification> predicate)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchUserNotifications(getClientId(), predicate);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void publishUserNotification(UserNotification notification)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().publishUserNotification(getClientId(), notification);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-API-Injection/src/main/java/org/opentcs/customizations/package-info.java<|end_filename|>
/**
 * Classes utilized for extending and customizing openTCS applications.
 */
package org.opentcs.customizations;


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerGroupEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Provides methods to edit layer groups.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerGroupEditor {

  /**
   * Sets a layer group's visible state.
   *
   * @param groupId The ID of the layer group.
   * @param visible The layer group's new visible state.
   */
  void setGroupVisible(int groupId, boolean visible);

  /**
   * Sets a layer group's name.
   *
   * @param groupId The ID of the layer group.
   * @param name The layer group's new name.
   */
  void setGroupName(int groupId, String name);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/Couple.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.Serializable;

/**
 * A generic 2-tuple of long integer values, usable for 2D coordinates and vectors, for instance.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Couple
    implements Serializable {

  /**
   * The X coordinate.
   */
  private final long x;
  /**
   * The Y coordinate.
   */
  private final long y;

  /**
   * Creates a new instance.
   *
   * @param x The X coordinate.
   * @param y The Y coordinate.
   */
  public Couple(long x, long y) {
    this.x = x;
    this.y = y;
  }

  /**
   * Returns the x coordinate.
   *
   * @return x
   */
  public long getX() {
    return x;
  }

  /**
   * Returns the y coordinate.
   *
   * @return y
   */
  public long getY() {
    return y;
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof Couple)) {
      return false;
    }
    Couple other = (Couple) obj;
    if (this.x != other.x) {
      return false;
    }
    if (this.y != other.y) {
      return false;
    }
    return true;
  }

  @Override
  public int hashCode() {
    return (int) (x ^ y);
  }

  @Override
  public String toString() {
    return "Couple{" + "x=" + x + ", y=" + y + '}';
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/messages/ClearError.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.messages;

import java.io.Serializable;

/**
 * A message that informs a communication adapter that it/the vehicle should
 * reset currently active errors if possible.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ClearError
    implements Serializable {

  /**
   * Creates a new instance.
   */
  public ClearError() {
    // Do nada.
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/PointModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.Arrays;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;
import org.opentcs.data.model.visualization.ElementPropKeys;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.layer.NullLayerWrapper;
import org.opentcs.guing.components.properties.type.AngleProperty;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.LayerWrapperProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.PointTypeProperty;
import org.opentcs.guing.components.properties.type.SelectionProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.model.AbstractConnectableModelComponent;
import org.opentcs.guing.model.AbstractModelComponent;
import org.opentcs.guing.model.FigureDecorationDetails;
import org.opentcs.guing.model.PositionableModelComponent;

/**
 * Basic implementation of a point.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class PointModel
    extends AbstractConnectableModelComponent
    implements PositionableModelComponent,
               FigureDecorationDetails {

  /**
   * Key for the prefered angle of a vehicle on this point.
   */
  public static final String VEHICLE_ORIENTATION_ANGLE = "vehicleOrientationAngle";
  /**
   * Key for the type.
   */
  public static final String TYPE = "Type";
  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * The point's default position for both axes.
   */
  private static final int DEFAULT_XY_POSITION = 0;
  /**
   * The set of vehicle models for which this model component's figure is to be decorted to
   * indicate that it is part of the route of the respective vehicles.
   */
  private Set<VehicleModel> vehicles
      = new TreeSet<>((v1, v2) -> v1.getName().compareTo(v2.getName()));
  /**
   * The set of block models for which this model component's figure is to be decorated to indicate
   * that it is part of the respective block.
   */
  private Set<BlockModel> blocks
      = new TreeSet<>((b1, b2) -> b1.getName().compareTo(b2.getName()));

  /**
   * Creates a new instance.
   */
  public PointModel() {
    createProperties();
  }

  @Override // AbstractModelComponent
  public String getDescription() {
    return bundle.getString("pointModel.description");
  }

  public CoordinateProperty getPropertyModelPositionX() {
    return (CoordinateProperty) getProperty(MODEL_X_POSITION);
  }

  public CoordinateProperty getPropertyModelPositionY() {
    return (CoordinateProperty) getProperty(MODEL_Y_POSITION);
  }

  public AngleProperty getPropertyVehicleOrientationAngle() {
    return (AngleProperty) getProperty(VEHICLE_ORIENTATION_ANGLE);
  }

  @SuppressWarnings("unchecked")
  public SelectionProperty<Type> getPropertyType() {
    return (SelectionProperty<Type>) getProperty(TYPE);
  }

  public KeyValueSetProperty getPropertyMiscellaneous() {
    return (KeyValueSetProperty) getProperty(MISCELLANEOUS);
  }

  public StringProperty getPropertyLayoutPosX() {
    return (StringProperty) getProperty(ElementPropKeys.POINT_POS_X);
  }

  public StringProperty getPropertyLayoutPosY() {
    return (StringProperty) getProperty(ElementPropKeys.POINT_POS_Y);
  }

  public StringProperty getPropertyPointLabelOffsetX() {
    return (StringProperty) getProperty(ElementPropKeys.POINT_LABEL_OFFSET_X);
  }

  public StringProperty getPropertyPointLabelOffsetY() {
    return (StringProperty) getProperty(ElementPropKeys.POINT_LABEL_OFFSET_Y);
  }

  public StringProperty getPropertyPointLabelOrientationAngle() {
    return (StringProperty) getProperty(ElementPropKeys.POINT_LABEL_ORIENTATION_ANGLE);
  }

  @Override
  public void addVehicleModel(VehicleModel model) {
    vehicles.add(model);
  }

  @Override
  public void removeVehicleModel(VehicleModel model) {
    vehicles.remove(model);
  }

  @Override
  public Set<VehicleModel> getVehicleModels() {
    return vehicles;
  }

  @Override
  public void addBlockModel(BlockModel model) {
    blocks.add(model);
  }

  @Override
  public void removeBlockModel(BlockModel model) {
    blocks.remove(model);
  }

  @Override
  public Set<BlockModel> getBlockModels() {
    return blocks;
  }

  @Override
  @SuppressWarnings("unchecked")
  public AbstractModelComponent clone()
      throws CloneNotSupportedException {
    PointModel clone = (PointModel) super.clone();
    clone.setVehicleModels((Set<VehicleModel>) ((TreeSet<VehicleModel>) vehicles).clone());
    clone.setBlockModels((Set<BlockModel>) ((TreeSet<BlockModel>) blocks).clone());

    return clone;
  }

  private void createProperties() {
    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("pointModel.property_name.description"));
    pName.setHelptext(bundle.getString("pointModel.property_name.helptext"));
    setProperty(NAME, pName);

    CoordinateProperty pPosX = new CoordinateProperty(this,
                                                      DEFAULT_XY_POSITION,
                                                      LengthProperty.Unit.MM);
    pPosX.setDescription(bundle.getString("pointModel.property_modelPositionX.description"));
    pPosX.setHelptext(bundle.getString("pointModel.property_modelPositionX.helptext"));
    setProperty(MODEL_X_POSITION, pPosX);

    CoordinateProperty pPosY = new CoordinateProperty(this,
                                                      DEFAULT_XY_POSITION,
                                                      LengthProperty.Unit.MM);
    pPosY.setDescription(bundle.getString("pointModel.property_modelPositionY.description"));
    pPosY.setHelptext(bundle.getString("pointModel.property_modelPositionY.helptext"));
    setProperty(MODEL_Y_POSITION, pPosY);

    AngleProperty pPhi = new AngleProperty(this);
    pPhi.setDescription(bundle.getString("pointModel.property_angle.description"));
    pPhi.setHelptext(bundle.getString("pointModel.property_angle.helptext"));
    setProperty(VEHICLE_ORIENTATION_ANGLE, pPhi);

    PointTypeProperty pType = new PointTypeProperty(this,
                                                    Arrays.asList(Type.values()),
                                                    Type.values()[0]);
    pType.setDescription(bundle.getString("pointModel.property_type.description"));
    pType.setHelptext(bundle.getString("pointModel.property_type.helptext"));
    pType.setCollectiveEditable(true);
    setProperty(TYPE, pType);

    KeyValueSetProperty pMiscellaneous = new KeyValueSetProperty(this);
    pMiscellaneous.setDescription(bundle.getString("pointModel.property_miscellaneous.description"));
    pMiscellaneous.setHelptext(bundle.getString("pointModel.property_miscellaneous.helptext"));
    pMiscellaneous.setOperatingEditable(true);
    setProperty(MISCELLANEOUS, pMiscellaneous);

    StringProperty pPointPosX = new StringProperty(this, String.valueOf(DEFAULT_XY_POSITION));
    pPointPosX.setDescription(bundle.getString("pointModel.property_positionX.description"));
    pPointPosX.setHelptext(bundle.getString("pointModel.property_positionX.helptext"));
    // The position can only be changed in the drawing.
    pPointPosX.setModellingEditable(false);
    setProperty(ElementPropKeys.POINT_POS_X, pPointPosX);

    StringProperty pPointPosY = new StringProperty(this, String.valueOf(DEFAULT_XY_POSITION));
    pPointPosY.setDescription(bundle.getString("pointModel.property_positionY.description"));
    pPointPosY.setHelptext(bundle.getString("pointModel.property_positionY.helptext"));
    // The position can only be changed in the drawing.
    pPointPosY.setModellingEditable(false);
    setProperty(ElementPropKeys.POINT_POS_Y, pPointPosY);

    StringProperty pPointLabelOffsetX = new StringProperty(this);
    pPointLabelOffsetX.setDescription(bundle.getString("pointModel.property_labelOffsetX.description"));
    pPointLabelOffsetX.setHelptext(bundle.getString("pointModel.property_labelOffsetX.helptext"));
    pPointLabelOffsetX.setModellingEditable(false);
    setProperty(ElementPropKeys.POINT_LABEL_OFFSET_X, pPointLabelOffsetX);

    StringProperty pPointLabelOffsetY = new StringProperty(this);
    pPointLabelOffsetY.setDescription(bundle.getString("pointModel.property_labelOffsetY.description"));
    pPointLabelOffsetY.setHelptext(bundle.getString("pointModel.property_labelOffsetY.helptext"));
    pPointLabelOffsetY.setModellingEditable(false);
    setProperty(ElementPropKeys.POINT_LABEL_OFFSET_Y, pPointLabelOffsetY);

    StringProperty pPointLabelOrientationAngle = new StringProperty(this);
    pPointLabelOrientationAngle.setDescription(
        bundle.getString("pointModel.property_labelOrientationAngle.description"));
    pPointLabelOrientationAngle.setHelptext(
        bundle.getString("pointModel.property_labelOrientationAngle.helptext"));
    pPointLabelOrientationAngle.setModellingEditable(false);
    setProperty(ElementPropKeys.POINT_LABEL_ORIENTATION_ANGLE, pPointLabelOrientationAngle);

    LayerWrapperProperty pLayerWrapper = new LayerWrapperProperty(this, new NullLayerWrapper());
    pLayerWrapper.setDescription(bundle.getString("pointModel.property_layerWrapper.description"));
    pLayerWrapper.setHelptext(bundle.getString("pointModel.property_layerWrapper.helptext"));
    pLayerWrapper.setModellingEditable(false);
    setProperty(LAYER_WRAPPER, pLayerWrapper);
  }

  private void setVehicleModels(Set<VehicleModel> vehicles) {
    this.vehicles = vehicles;
  }
  
  private void setBlockModels(Set<BlockModel> blocks) {
    this.blocks = blocks;
  }

  /**
   * The supported point types.
   */
  public enum Type {

    /**
     * A halting position.
     */
    HALT(ResourceBundle.getBundle(BUNDLE_PATH).getString("pointModel.type.halt.description"),
         ResourceBundle.getBundle(BUNDLE_PATH).getString("pointModel.type.halt.helptext")),
    /**
     * A reporting position.
     */
    REPORT(ResourceBundle.getBundle(BUNDLE_PATH).getString("pointModel.type.report.description"),
           ResourceBundle.getBundle(BUNDLE_PATH).getString("pointModel.type.report.helptext")),
    /**
     * A parking position.
     */
    PARK(ResourceBundle.getBundle(BUNDLE_PATH).getString("pointModel.type.park.description"),
         ResourceBundle.getBundle(BUNDLE_PATH).getString("pointModel.type.park.helptext"));

    private final String description;
    private final String helptext;

    private Type(String description, String helptext) {
      this.description = requireNonNull(description, "description");
      this.helptext = requireNonNull(helptext, "helptext");
    }

    public String getDescription() {
      return description;
    }

    public String getHelptext() {
      return helptext;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerChangeListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Listens for changes to/updates on layer data.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerChangeListener {

  /**
   * Notifies the listener that the layer data has been initialized.
   */
  void layersInitialized();

  /**
   * Notifies the listener that some layer data has changed.
   */
  void layersChanged();

  /**
   * Notifies the listener that a layer has been added.
   */
  void layerAdded();

  /**
   * Notifies the listener that a layer has been removed.
   */
  void layerRemoved();
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/PeripheralControllerFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralController;

/**
 * A factory for {@link PeripheralController} instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralControllerFactory {

  /**
   * Creates a new peripheral controller for the given location and communication adapter.
   *
   * @param location The location.
   * @param commAdapter The communication adapter.
   * @return A new peripheral controller.
   */
  DefaultPeripheralController createVehicleController(TCSResourceReference<Location> location,
                                                      PeripheralCommAdapter commAdapter);
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/ModelComponent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.List;
import java.util.Map;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.components.properties.type.StringProperty;

/**
 * Defines a component in the system model.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface ModelComponent
    extends Cloneable {

  /**
   * Key for the name property.
   */
  String NAME = "Name";
  /**
   * Key for the miscellaneous properties.
   */
  String MISCELLANEOUS = "Miscellaneous";

  /**
   * Adds a child component.
   *
   * @param component The model component to add.
   */
  void add(ModelComponent component);

  /**
   * Removes a child component.
   *
   * @param component The model component to remove.
   */
  void remove(ModelComponent component);

  /**
   * Returns all child components.
   *
   * @return A list of all child components.
   */
  List<ModelComponent> getChildComponents();

  /**
   * Retruns this model component's name that is displayed in the tree view.
   *
   * @return The name that is displayed in the tree view.
   */
  String getTreeViewName();

  /**
   * Returns whether the given component is a child of this model component.
   *
   * @param component The component.
   * @return {@code true}, if the given component is a child of this model component, otherwise
   * {@code false}.
   */
  boolean contains(ModelComponent component);

  /**
   * Returns this model component's parent component.
   *
   * @return The parent component.
   */
  ModelComponent getParent();

  /**
   * Returns the actual parent of this model component.
   * PropertiesCollection e.g. overwrites it. May be null.
   *
   * @return The actual parent.
   */
  ModelComponent getActualParent();

  /**
   * Set this model component's parent component.
   *
   * @param parent The new parent component.
   */
  void setParent(ModelComponent parent);

  /**
   * Returns whether this model component is to be shown in the tree view.
   *
   * @return {@code true}, if the model component is to be shown in the tree view, otherwise {@code false}.
   */
  boolean isTreeViewVisible();

  /**
   * Sets this model component's visibility in the tree view.
   *
   * @param visibility Whether the model component is to be shown in the tree view or not.
   */
  void setTreeViewVisibility(boolean visibility);

  /**
   * Returns a description for the model component.
   *
   * @return A description for the model component.
   */
  String getDescription();

  /**
   * Returns the name of the component.
   *
   * @return The name of the component.
   */
  String getName();

  /**
   * Sets this model component's name.
   *
   * @param name The new name.
   */
  void setName(String name);

  /**
   * Returns the property with the given name.
   *
   * @param name The name of the property.
   * @return The property with the given name.
   */
  Property getProperty(String name);

  /**
   * Returns all properties.
   *
   * @return A map containing all properties.
   */
  Map<String, Property> getProperties();

  /**
   * Sets the property with the given name.
   *
   * @param name The name of the property.
   * @param property The property.
   */
  void setProperty(String name, Property property);

  /**
   * Returns this component's name property.
   *
   * @return This component's name property.
   */
  default StringProperty getPropertyName() {
    return (StringProperty) getProperty(NAME);
  }

  /**
   * Adds the given {@link AttributesChangeListener}.
   * The {@link AttributesChangeListener} is notified when properties of the model component
   * have changed.
   *
   * @param l The listener.
   */
  void addAttributesChangeListener(AttributesChangeListener l);

  /**
   * Removes the given {@link AttributesChangeListener}.
   *
   * @param l The listener.
   */
  void removeAttributesChangeListener(AttributesChangeListener l);

  /**
   * Returns whether the given {@link AttributesChangeListener} is already registered with the model
   * component.
   *
   * @param l The listener.
   * @return {@code true}, if the given {@link AttributesChangeListener} is already registered with the model
   * component, otherwise {@code false}.
   */
  boolean containsAttributesChangeListener(AttributesChangeListener l);

  /**
   * Notifies all registered {@link AttributesChangeListener}s that properties of the model
   * component have changed.
   *
   * @param l The initiator of the change.
   */
  void propertiesChanged(AttributesChangeListener l);

  /**
   * Clones this ModelComponent.
   *
   * @return A clone of this ModelComponent.
   * @throws java.lang.CloneNotSupportedException If the model component doesn't implement the
   * {@link Cloneable} interface.
   */
  ModelComponent clone()
      throws CloneNotSupportedException;
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/adapter/PathAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import java.util.Arrays;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.stream.Collectors;
import org.opentcs.access.to.model.PathCreationTO;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObject;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Path;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.SpeedProperty;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.PeripheralOperationModel;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.PathModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An adapter for Path objects.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class PathAdapter
    extends AbstractProcessAdapter {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PathAdapter.class);

  @Override
  public void updateModelProperties(TCSObject<?> tcsObject,
                                    ModelComponent modelComponent,
                                    SystemModel systemModel,
                                    TCSObjectService objectService) {
    Path path = requireNonNull((Path) tcsObject, "tcsObject");
    PathModel model = (PathModel) modelComponent;

    model.getPropertyName().setText(path.getName());
    model.getPropertyStartComponent().setText(path.getSourcePoint().getName());
    model.getPropertyEndComponent().setText(path.getDestinationPoint().getName());
    model.getPropertyLength().setValueAndUnit(path.getLength(), LengthProperty.Unit.MM);
    model.getPropertyMaxVelocity().setValueAndUnit(path.getMaxVelocity(),
                                                   SpeedProperty.Unit.MM_S);
    model.getPropertyMaxReverseVelocity().setValueAndUnit(path.getMaxReverseVelocity(),
                                                          SpeedProperty.Unit.MM_S);
    model.getPropertyLocked().setValue(path.isLocked());
    for (PeripheralOperation operation : path.getPeripheralOperations()) {
      model.getPropertyPeripheralOperations().getValue().add(
          new PeripheralOperationModel(operation.getLocation().getName(),
                                       operation.getOperation(),
                                       operation.getExecutionTrigger(),
                                       operation.isCompletionRequired())
      );
    }

    updateMiscModelProperties(model, path);
    updateModelLayoutProperties(model, path, systemModel.getLayoutModel());
    model.propertiesChanged(model);
  }

  @Override
  public PlantModelCreationTO storeToPlantModel(ModelComponent modelComponent,
                                                SystemModel systemModel,
                                                PlantModelCreationTO plantModel) {
    PathModel pathModel = (PathModel) modelComponent;

    LOG.debug("Path {}: srcPoint is {}, dstPoint is {}.",
              pathModel.getName(),
              getSourcePoint(pathModel),
              getDestinationPoint(pathModel));

    PlantModelCreationTO result = plantModel
        .withPath(
            new PathCreationTO(pathModel.getName(),
                               getSourcePoint(pathModel),
                               getDestinationPoint(pathModel))
                .withLength(getLength(pathModel))
                .withMaxVelocity(getMaxVelocity(pathModel))
                .withMaxReverseVelocity(getMaxReverseVelocity(pathModel))
                .withProperties(getKernelProperties(pathModel))
                .withLocked(getLocked(pathModel))
                .withPeripheralOperations(getPeripheralOperations(pathModel))
                .withLayout(getLayout(pathModel))
        );

    unmarkAllPropertiesChanged(pathModel);

    return result;
  }

  private void updateModelLayoutProperties(PathModel model, Path path, LayoutModel layoutModel) {
    model.getPropertyPathConnType()
        .setValue(toPathModelConnectionType(path.getLayout().getConnectionType()));
    String controlPointsString = path.getLayout().getControlPoints().stream()
        .map(point -> String.format("%d,%d", point.getX(), point.getY()))
        .collect(Collectors.joining(";"));
    model.getPropertyPathControlPoints().setText(controlPointsString);
    LayerWrapper layerWrapper = layoutModel.getPropertyLayerWrappers()
        .getValue().get(path.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);
  }

  private PathModel.Type toPathModelConnectionType(Path.Layout.ConnectionType connectionType) {
    PathModel.Type result = PathModel.Type.DIRECT;

    switch (connectionType) {
      case DIRECT:
        result = PathModel.Type.DIRECT;
        break;
      case ELBOW:
        result = PathModel.Type.ELBOW;
        break;
      case SLANTED:
        result = PathModel.Type.SLANTED;
        break;
      case POLYPATH:
        result = PathModel.Type.POLYPATH;
        break;
      case BEZIER:
        result = PathModel.Type.BEZIER;
        break;
      case BEZIER_3:
        result = PathModel.Type.BEZIER_3;
        break;
      default:
        throw new IllegalArgumentException("Unhandled connection type: " + connectionType);
    }

    return result;
  }

  private boolean getLocked(PathModel model) {
    if (model.getPropertyLocked().getValue() instanceof Boolean) {
      return (boolean) model.getPropertyLocked().getValue();
    }
    return false;
  }

  private int getMaxVelocity(PathModel model) {
    return (int) Math.abs(model.getPropertyMaxVelocity()
        .getValueByUnit(SpeedProperty.Unit.MM_S));
  }

  private int getMaxReverseVelocity(PathModel model) {
    return (int) Math.abs(model.getPropertyMaxReverseVelocity()
        .getValueByUnit(SpeedProperty.Unit.MM_S));
  }

  private String getSourcePoint(PathModel model) {
    return model.getPropertyStartComponent().getText();
  }

  private String getDestinationPoint(PathModel model) {
    return model.getPropertyEndComponent().getText();
  }

  private long getLength(PathModel model) {
    LengthProperty pLength = model.getPropertyLength();

    if ((double) pLength.getValue() <= 0) {
      try {
        pLength.setValueAndUnit(1.0, pLength.getUnit());
        pLength.markChanged();
      }
      catch (IllegalArgumentException ex) {
        LOG.warn("", ex);
      }
    }

    return (long) pLength.getValueByUnit(LengthProperty.Unit.MM);
  }

  private PathCreationTO.Layout getLayout(PathModel model) {
    List<Couple> controlPoints
        = Arrays.asList(model.getPropertyPathControlPoints().getText().split(";")).stream()
            .filter(controlPointString -> !controlPointString.isEmpty())
            .map(controlPointString -> {
              String[] coordinateStrings = controlPointString.split(",");
              return new Couple(Long.parseLong(coordinateStrings[0]),
                                Long.parseLong(coordinateStrings[1]));
            })
            .collect(Collectors.toList());

    return new PathCreationTO.Layout(
        toPathConnectionType((PathModel.Type) model.getPropertyPathConnType().getValue()),
        controlPoints,
        model.getPropertyLayerWrapper().getValue().getLayer().getId()
    );
  }

  private Path.Layout.ConnectionType toPathConnectionType(PathModel.Type type) {
    Path.Layout.ConnectionType result = Path.Layout.ConnectionType.DIRECT;

    switch (type) {
      case DIRECT:
        result = Path.Layout.ConnectionType.DIRECT;
        break;
      case ELBOW:
        result = Path.Layout.ConnectionType.ELBOW;
        break;
      case SLANTED:
        result = Path.Layout.ConnectionType.SLANTED;
        break;
      case POLYPATH:
        result = Path.Layout.ConnectionType.POLYPATH;
        break;
      case BEZIER:
        result = Path.Layout.ConnectionType.BEZIER;
        break;
      case BEZIER_3:
        result = Path.Layout.ConnectionType.BEZIER_3;
        break;
      default:
        throw new IllegalArgumentException("Unhandled connection type: " + type);
    }

    return result;
  }

  private List<PeripheralOperationCreationTO> getPeripheralOperations(PathModel path) {
    return path.getPropertyPeripheralOperations().getValue().stream()
        .map(model
            -> new PeripheralOperationCreationTO(model.getOperation(), model.getLocationName())
            .withExecutionTrigger(model.getExecutionTrigger())
            .withCompletionRequired(model.isCompletionRequired())
        )
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/layer/LayerWrapper.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.model.ModelComponent;

/**
 * Wraps a {@link Layer} instance and the {@link LayerGroup} instance that the layer is assigned to.
 * Instances of this class are referenced by {@link ModelComponent}s. This allows multiple model
 * components to be updated simultaneously with the update of only one layer wrapper.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerWrapper {

  /**
   * The layer.
   */
  private Layer layer;
  /**
   * The layer group the layer is assigned to.
   */
  private LayerGroup layerGroup;

  /**
   * Creates a new instance.
   *
   * @param layer The layer.
   * @param layerGroup The layer group the layer is assigned to.
   */
  public LayerWrapper(@Nonnull Layer layer, @Nonnull LayerGroup layerGroup) {
    this.layer = requireNonNull(layer, "layer");
    this.layerGroup = requireNonNull(layerGroup, "layerGroup");
  }

  /**
   * Returns the layer.
   *
   * @return The layer.
   */
  @Nonnull
  public Layer getLayer() {
    return layer;
  }

  /**
   * Sets the layer.
   *
   * @param layer The layer.
   */
  public void setLayer(@Nonnull Layer layer) {
    this.layer = requireNonNull(layer, "layer");
  }

  /**
   * Returns the layer group the layer is assigned to.
   *
   * @return The layer group.
   */
  public LayerGroup getLayerGroup() {
    return layerGroup;
  }

  /**
   * Sets the layer group the layer is assigned to.
   *
   * @param layerGroup The layer group.
   */
  public void setLayerGroup(LayerGroup layerGroup) {
    this.layerGroup = layerGroup;
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/package-info.java<|end_filename|>
/**
 * Generic GUI components for input dialogs.
 */
package org.opentcs.virtualvehicle.inputcomponents;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/OrderSequenceCleanupApproval.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import java.util.function.Predicate;
import org.opentcs.data.order.OrderSequence;

/**
 * Implementations of this interface check whether an order sequence may be removed.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OrderSequenceCleanupApproval
    extends Predicate<OrderSequence> {

}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/LocalVehicleControllerPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import org.opentcs.components.Lifecycle;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.drivers.vehicle.VehicleControllerPool;

/**
 * Manages the attachment of vehicle controllers to vehicles and comm adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LocalVehicleControllerPool
    extends VehicleControllerPool,
            Lifecycle{

  /**
   * Associates a vehicle controller with a named vehicle and a comm adapter.
   *
   * @param vehicleName The name of the vehicle.
   * @param commAdapter The communication adapter that is going to control the physical vehicle.
   */
  void attachVehicleController(String vehicleName, VehicleCommAdapter commAdapter)
      throws IllegalArgumentException;

  /**
   * Disassociates a vehicle control and a comm adapter from a vehicle.
   *
   * @param vehicleName The name of the vehicle from which to detach.
   */
  void detachVehicleController(String vehicleName);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/DefaultPeripheralJobDispatcherConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the {@link DefaultPeripheralJobDispatcher}
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(DefaultPeripheralJobDispatcherConfiguration.PREFIX)
public interface DefaultPeripheralJobDispatcherConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "defaultperipheraljobdispatcher";

  @ConfigurationEntry(
      type = "Integer",
      description = "The interval between redispatching of peripheral devices.",
      orderKey = "9_misc")
  long idlePeripheralRedispatchingInterval();
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/drawing/OpenTCSDrawingEditorOperating.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.SwingUtilities;
import org.opentcs.guing.components.drawing.figures.NamedVehicleFigure;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.NullAttributesChangeListener;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.VehicleCourseObjectFactory;

/**
 * The <code>DrawingEditor</code> coordinates <code>DrawingViews</code>
 * and the <code>Drawing</code>.
 * It also offers methods to add specific unique figures to the
 * <code>Drawing</code>.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSDrawingEditorOperating
    extends OpenTCSDrawingEditor {

  /**
   * Provides the current system model.
   */
  private final ModelManager modelManager;
  /**
   * A factory for course objects.
   */
  private final VehicleCourseObjectFactory courseObjectFactory;

  /**
   * Creates a new instance.
   *
   * @param courseObjectFactory A factory for course objects.
   * @param modelManager Provides the current system model.
   */
  @Inject
  public OpenTCSDrawingEditorOperating(VehicleCourseObjectFactory courseObjectFactory,
                                       ModelManager modelManager) {
    super(courseObjectFactory);
    this.courseObjectFactory = requireNonNull(courseObjectFactory, "courseObjectFactory");
    this.modelManager = requireNonNull(modelManager, "modelManager");
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof SystemModelTransitionEvent) {
      handleSystemModelTransition((SystemModelTransitionEvent) event);
    }
  }

  private void handleSystemModelTransition(SystemModelTransitionEvent evt) {
    switch (evt.getStage()) {
      case UNLOADING:
        // XXX Remove vehicles?
        break;
      case LOADED:
        setVehicles(modelManager.getModel().getVehicleModels());
//        initializeOffsetFigures();
        break;
      default:
      // Do nada.
    }
  }

  /**
   * Adds the given vehicles to the drawing.
   *
   * @param vehicleModels The <code>VehicleModels</code> to add.
   */
  public void setVehicles(List<VehicleModel> vehicleModels) {
    for (VehicleModel vehicleComp : vehicleModels) {
      addVehicle(vehicleComp);
    }
  }

  /**
   * Adds a vehicle to the drawing.
   *
   * @param vehicleModel The vehicle model to add.
   */
  public void addVehicle(VehicleModel vehicleModel) {
    NamedVehicleFigure vehicleFigure
        = courseObjectFactory.createNamedVehicleFigure(vehicleModel);

    SwingUtilities.invokeLater(() -> getDrawing().add(vehicleFigure));

    vehicleModel.addAttributesChangeListener(vehicleFigure);
    modelManager.getModel().registerFigure(vehicleModel, vehicleFigure);

    vehicleModel.setDisplayDriveOrders(true);
    for (OpenTCSDrawingView view : getAllViews()) {
      view.displayDriveOrders(vehicleModel, true);
    }
    vehicleFigure.propertiesChanged(new AttributesChangeEvent(new NullAttributesChangeListener(), vehicleModel));
  }
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/documentation/WithdrawTransportOrderTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.documentation;

import java.util.Collections;
import org.junit.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;

/**
 * Test for the developers asciidoc documentation to show how a tranport order is withdrawn.
 * This test has no meaning and it just exists for the documentation to refer to and to guarantee
 * an example that compiles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class WithdrawTransportOrderTest {

  private DispatcherService dispService;
  private TCSObjectService objService;
  private Vehicle vehicle;

  @Before
  public void setUp() {
    dispService = mock(DispatcherService.class);
    objService = mock(TCSObjectService.class);
    vehicle = new Vehicle("Vehicle");
    when(objService.fetchObject(eq(Vehicle.class), any(String.class))).thenReturn(vehicle);
  }

  @Test
  public void shouldWithdrawTransportOrder() {
    // tag::documentation_withdrawTransportOrder[]
    // The dispatcher service instance we're working with
    DispatcherService dispatcherService = getDispatcherServiceFromSomewhere();

    // Get the transport order to be withdrawn.
    TransportOrder curOrder = getTransportOrderToWithdraw();
    // Withdraw the order.
    // The second argument indicates if the vehicle should finish the movements
    // it is already assigned to (false) or abort immediately (true).
    dispatcherService.withdrawByTransportOrder(curOrder.getReference(), true);
    // end::documentation_withdrawTransportOrder[]
  }

  @Test
  public void shouldWithdrawTransportOrderByVehicle() {
    // tag::documentation_withdrawTransportOrderByVehicle[]
    // The object service instance we're working with
    TCSObjectService objectService = getTCSObjectServiceFromSomewhere();

    // Get the vehicle from which the transport order shall be withdrawn
    Vehicle curVehicle = objectService.fetchObject(Vehicle.class,
                                                   getSampleVehicle());

    // The dispatcher service instance we're working with
    DispatcherService dispatcherService = getDispatcherServiceFromSomewhere();

    // Withdraw the order.
    // The second argument indicates if the vehicle should finish the movements
    // it is already assigned to (false) or abort immediately (true).
    dispatcherService.withdrawByVehicle(curVehicle.getReference(), true);
    // end::documentation_withdrawTransportOrderByVehicle[]
  }

  private Location getSampleDestinationLocation() {
    return new Location("Location", new LocationType("LocationType").getReference());
  }

  private String getSampleVehicle() {
    return "";
  }

  private DispatcherService getDispatcherServiceFromSomewhere() {
    return dispService;
  }

  private TCSObjectService getTCSObjectServiceFromSomewhere() {
    return objService;
  }

  private TransportOrder getTransportOrderToWithdraw() {
    return new TransportOrder(
        "Transportorder",
        Collections.singletonList(new DriveOrder(
            new DriveOrder.Destination(getSampleDestinationLocation().getReference())
                .withOperation(getDestinationOperation()))));
  }

  private String getDestinationOperation() {
    return "";
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/TripleProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.opentcs.data.model.Triple;
import org.opentcs.guing.model.ModelComponent;
import org.slf4j.LoggerFactory;

/**
 * A property for a 3 dimensional point.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TripleProperty
    extends AbstractProperty {

  /**
   * The point.
   */
  private Triple fTriple;

  /**
   * Creates a new instance.
   *
   * @param model The model component.
   */
  public TripleProperty(ModelComponent model) {
    super(model);
  }

  @Override
  public Object getComparableValue() {
    return fTriple.getX() + "," + fTriple.getY() + "," + fTriple.getZ();
  }

  /**
   * Set the value of this property.
   *
   * @param triple The triple.
   */
  public void setValue(Triple triple) {
    fTriple = triple;
  }

  @Override
  public Triple getValue() {
    return fTriple;
  }

  @Override
  public String toString() {
    return fTriple == null ? "null"
        : String.format("(%d, %d, %d)", fTriple.getX(), fTriple.getY(), fTriple.getZ());
  }

  @Override
  public void copyFrom(Property property) {
    TripleProperty tripleProperty = (TripleProperty) property;

    try {
      Triple foreignTriple = tripleProperty.getValue();
      setValue(foreignTriple);
    }
    catch (Exception e) {
      LoggerFactory.getLogger(TripleProperty.class).error("Exception", e);
    }
  }
}


<|start_filename|>openTCS-Impl-Configuration-cfg4j/src/main/java/org/opentcs/configuration/cfg4j/SupplementaryConfigurationSource.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.configuration.cfg4j;

import org.cfg4j.source.ConfigurationSource;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface SupplementaryConfigurationSource
    extends ConfigurationSource {

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/TreeView.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree;

import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Set;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import org.opentcs.guing.components.tree.elements.UserObject;

/**
 * A TreeView manages a model which has a set of TreeNode objects.
 * Each TreeNode has a UserObject. Each UserObject wraps a real object 
 * (e.g. Article, Figure, ...). It knows which methods to call to when an object is selected 
 * in the tree or is deleted or is double-clicked.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @see UserObject
 */
public interface TreeView {

  /**
   * Adds an item to the tree.
   * 
   * @param parent A real object that is seached in the tree.
   * @param item Is a UserObject.
   */
  void addItem(Object parent, UserObject item);

  /**
   * Sorts the children of the given node.
   *
   * @param treeNode The node whose children shall be sorted.
   */
  void sortItems(TreeNode treeNode);

  /**
   * Returns the <code>JTree</code> that actually holds the objects.
   *
   * @return The tree.
   */
  JTree getTree();

  /**
   * Adds the given listener to the <code>JTree</code>.
   *
   * @param mouseListener The listener.
   */
  void addMouseListener(MouseListener mouseListener);

  /**
   * Adds the given motion listener to the <code>JTree</code>.
   *
   * @param mouseMotionListener The motion listener.
   */
  void addMouseMotionListener(MouseMotionListener mouseMotionListener);

  /**
   * Updates the text at the top of the <code>JTree</code>.
   *
   * @param text The new text.
   */
  void updateText(String text);

  /**
   * Returns whether the tree has buffered objects.
   *
   * @return <code>true</code> if it has some.
   */
  boolean hasBufferedObjects();

  /**
   * Returns the dragged user object.
   *
   * @param e The event where the mouse click happened.
   * @return The user object that was dragged.
   */
  UserObject getDraggedUserObject(MouseEvent e);

  /**
   * Sets the cursor of the <code>JTree</code>.
   *
   * @param cursor The new cursor.
   */
  void setCursor(Cursor cursor);

  /**
   * Removes an item from the tree.
   *
   * @param item A real object.
   */
  void removeItem(Object item);

  /**
   * Removes all child elements from an item.
   *
   * @param item The item to remove child elements from.
   */
  void removeChildren(Object item);

  /**
   * Selects an item in the tree.
   *
   * @param item The item to select.
   */
  void selectItem(Object item);

  /**
   * Selects a set of items in the tree.
   *
   * @param items The set of items to select.
   */
  void selectItems(Set<?> items);

  /**
   * Notifies the tree that a property of the specified item has changed.
   *
   * @param item
   */
  void itemChanged(Object item);

  /**
   * Return the selected item.
   *
   * @return the selected item.
   */
  UserObject getSelectedItem();

  /**
   * Return the selected items.
   *
   * @return the selected items.
   */
  Set<UserObject> getSelectedItems();

  /**
   * Sorts the root element of the tree.
   */
  void sortRoot();

  /**
   * Sorts all children.
   */
  void sortChildren();
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/CallWrapper.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.util.concurrent.Callable;

/**
 * Provides methods for wrapping other method calls.
 * This can be useful to ensure preparations have been done for a larger set of various method
 * calls, for example.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface CallWrapper {

  /**
   * Calls a method that has a return value.
   *
   * @param <R> The return value's type.
   * @param callable The method wrapped in a {@link Callable} instance.
   * @return The result of the method's call.
   * @throws Exception If there was an exception calling method.
   */
  <R> R call(Callable<R> callable)
      throws Exception;

  /**
   * Calls a mehtod that has no return value.
   *
   * @param runnable The method wrapped in a {@link Runnable} instance.
   * @throws Exception If there was an exception calling method.
   */
  void call(Runnable runnable)
      throws Exception;
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/AbstractRemoteServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;

/**
 * An base class for remote service proxy implementations.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <R> The remote service's type.
 */
abstract class AbstractRemoteServiceProxy<R extends Remote> {

  /**
   * The message to log when a service is unavailable.
   */
  private static final String SERVICE_UNAVAILABLE_MESSAGE = "Remote service unreachable";
  /**
   * The client using this service.
   */
  private ClientID clientId;
  /**
   * The corresponding remote service.
   */
  private R remoteService;
  /**
   * The the listener that is interested in updates of this service.
   */
  private ServiceListener serviceListener;

  /**
   * Retruns the client id using this service.
   *
   * @return The client id using this service.
   */
  ClientID getClientId() {
    return clientId;
  }

  /**
   * Sets the client id using this service.
   *
   * @param clientId The client id.
   * @return This remote service proxy.
   */
  AbstractRemoteServiceProxy<R> setClientId(ClientID clientId) {
    this.clientId = clientId;
    return this;
  }

  /**
   * Returns the remote service to delegate method invocations to.
   *
   * @return The remote service to delegate method incocations to.
   */
  R getRemoteService() {
    return remoteService;
  }

  /**
   * Sets the remote service to delegate method invocations to.
   *
   * @param remoteService The remote service.
   * @return This remote service proxy.
   */
  AbstractRemoteServiceProxy<R> setRemoteService(R remoteService) {
    this.remoteService = remoteService;
    return this;
  }

  /**
   * Returns the listener that is interested in updates of this service.
   *
   * @return The listener that is interested in updates of this service.
   */
  ServiceListener getServiceListener() {
    return serviceListener;
  }

  /**
   * Sets the listener that is interested in updates of this service.
   *
   * @param serviceListener The service listener.
   * @return This remote service proxy.
   */
  public AbstractRemoteServiceProxy<R> setServiceListener(ServiceListener serviceListener) {
    this.serviceListener = serviceListener;
    return this;
  }

  /**
   * Checks whether this service is logged in or not.
   *
   * @return {@code true} if, and only if, this service has both a client id and a remote service
   * associated to it.
   */
  boolean isLoggedIn() {
    return (getClientId() != null && getRemoteService() != null);
  }

  /**
   * Ensures that this service is available to be used.
   *
   * @throws ServiceUnavailableException If the service is not available.
   */
  void checkServiceAvailability()
      throws ServiceUnavailableException {
    if (!isLoggedIn()) {
      throw new ServiceUnavailableException(SERVICE_UNAVAILABLE_MESSAGE);
    }
  }

  /**
   * Returns a suitable {@link RuntimeException} for the given {@link RemoteException}.
   *
   * @param ex The exception to find a runtime exception for.
   * @return The runtime exception.
   */
  RuntimeException findSuitableExceptionFor(RemoteException ex) {
    if (ex.getCause() instanceof ObjectUnknownException) {
      return (ObjectUnknownException) ex.getCause();
    }
    if (ex.getCause() instanceof ObjectExistsException) {
      return (ObjectExistsException) ex.getCause();
    }
    if (ex.getCause() instanceof IllegalArgumentException) {
      return (IllegalArgumentException) ex.getCause();
    }

    if (getServiceListener() != null) {
      getServiceListener().onServiceUnavailable();
    }

    return new ServiceUnavailableException(SERVICE_UNAVAILABLE_MESSAGE, ex);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemotePeripheralService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.Remote;
import java.rmi.RemoteException;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.PeripheralService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;

/**
 * Declares the methods provided by the {@link PeripheralService} via RMI.
 *
 * <p>
 * The majority of the methods declared here have signatures analogous to their counterparts in
 * {@link PeripheralService}, with an additional {@link ClientID} parameter which serves the purpose
 * of identifying the calling client and determining its permissions.
 * </p>
 * <p>
 * To avoid redundancy, the semantics of methods that only pass through their arguments are not
 * explicitly documented here again. See the corresponding API documentation in
 * {@link PeripheralService} for these, instead.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RemotePeripheralService
    extends RemoteTCSObjectService,
            Remote {

  // CHECKSTYLE:OFF
  void attachCommAdapter(ClientID clientId,
                         TCSResourceReference<Location> ref,
                         PeripheralCommAdapterDescription description)
      throws RemoteException;

  void disableCommAdapter(ClientID clientId, TCSResourceReference<Location> ref)
      throws RemoteException;

  void enableCommAdapter(ClientID clientId, TCSResourceReference<Location> ref)
      throws RemoteException;

  PeripheralAttachmentInformation fetchAttachmentInformation(ClientID clientId,
                                                             TCSResourceReference<Location> ref)
      throws RemoteException;

  PeripheralProcessModel fetchProcessModel(ClientID clientId, TCSResourceReference<Location> ref)
      throws RemoteException;

  void sendCommAdapterCommand(ClientID clientId,
                              TCSResourceReference<Location> ref,
                              PeripheralAdapterCommand command)
      throws RemoteException;
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/peripherals/package-info.java<|end_filename|>
/**
 * Classes describing peripheral jobs to be processed by peripheral devices.
 */
package org.opentcs.data.peripherals;


<|start_filename|>openTCS-API-Injection/src/main/java/org/opentcs/customizations/plantoverview/PlantOverviewInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.customizations.plantoverview;

import com.google.inject.multibindings.Multibinder;
import org.opentcs.components.plantoverview.ObjectHistoryEntryFormatter;
import org.opentcs.components.plantoverview.OrderTypeSuggestions;
import org.opentcs.components.plantoverview.PlantModelExporter;
import org.opentcs.components.plantoverview.PlantModelImporter;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import org.opentcs.components.plantoverview.PropertySuggestions;
import org.opentcs.customizations.ConfigurableInjectionModule;

/**
 * A base class for Guice modules adding or customizing bindings for the plant overview application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class PlantOverviewInjectionModule
    extends ConfigurableInjectionModule {

  /**
   * Returns a multibinder that can be used to register plant model importers.
   *
   * @return The multibinder.
   */
  protected Multibinder<PlantModelImporter> plantModelImporterBinder() {
    return Multibinder.newSetBinder(binder(), PlantModelImporter.class);
  }

  /**
   * Returns a multibinder that can be used to register plant model exporters.
   *
   * @return The multibinder.
   */
  protected Multibinder<PlantModelExporter> plantModelExporterBinder() {
    return Multibinder.newSetBinder(binder(), PlantModelExporter.class);
  }

  /**
   * Returns a multibinder that can be used to register factories for pluggable panels.
   *
   * @return The multibinder.
   */
  protected Multibinder<PluggablePanelFactory> pluggablePanelFactoryBinder() {
    return Multibinder.newSetBinder(binder(), PluggablePanelFactory.class);
  }

  /**
   * Returns a multibinder that can be used to register classes that provide suggested properties.
   *
   * @return The multibinder.
   */
  protected Multibinder<PropertySuggestions> propertySuggestionsBinder() {
    return Multibinder.newSetBinder(binder(), PropertySuggestions.class);
  }

  /**
   * Returns a multibinder that can be used to register classes that provide suggested order types.
   *
   * @return The multibinder.
   */
  protected Multibinder<OrderTypeSuggestions> orderTypeSuggestionsBinder() {
    return Multibinder.newSetBinder(binder(), OrderTypeSuggestions.class);
  }

  /**
   * Returns a multibinder that can be used to register {@link ObjectHistoryEntryFormatter}s.
   *
   * @return The multibinder.
   */
  protected Multibinder<ObjectHistoryEntryFormatter> objectHistoryEntryFormatterBinder() {
    return Multibinder.newSetBinder(binder(), ObjectHistoryEntryFormatter.class);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/peripherals/jobs/PeripheralJobsContainer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.peripherals.jobs;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.guing.event.KernelStateChangeEvent;
import org.opentcs.guing.event.OperationModeChangeEvent;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Maintains a set of all peripheral jobs existing on the kernel side.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralJobsContainer
    implements EventHandler,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralJobsContainer.class);
  /**
   * Where we get events from.
   */
  private final EventBus eventBus;
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * The peripheral jobs.
   */
  private final Map<String, PeripheralJob> peripheralJobs = new HashMap<>();
  /**
   * This container's listeners.
   */
  private final Set<PeripheralJobsContainerListener> listeners = new HashSet<>();
  /**
   * Whether this component is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param eventBus Where this instance subscribes for events.
   * @param portalProvider Provides a access to a portal.
   */
  @Inject
  public PeripheralJobsContainer(@ApplicationEventBus EventBus eventBus,
                                 SharedKernelServicePortalProvider portalProvider) {
    this.eventBus = requireNonNull(eventBus, "eventBus");
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventBus.subscribe(this);

    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventBus.unsubscribe(this);

    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof TCSObjectEvent) {
      handleObjectEvent((TCSObjectEvent) event);
    }
    else if (event instanceof OperationModeChangeEvent) {
      initJobs();
    }
    else if (event instanceof SystemModelTransitionEvent) {
      initJobs();
    }
    else if (event instanceof KernelStateChangeEvent) {
      initJobs();
    }
  }

  public void addListener(PeripheralJobsContainerListener listener) {
    listeners.add(listener);
  }

  public void removeListener(PeripheralJobsContainerListener listener) {
    listeners.remove(listener);
  }

  public Collection<PeripheralJob> getPeripheralJobs() {
    return peripheralJobs.values();
  }

  private void initJobs() {
    setPeripheralJobs(fetchJobsIfOnline());
    listeners.forEach(listener -> listener.containerInitialized(peripheralJobs.values()));
  }

  private void handleObjectEvent(TCSObjectEvent evt) {
    if (evt.getCurrentOrPreviousObjectState() instanceof PeripheralJob) {
      switch (evt.getType()) {
        case OBJECT_CREATED:
          peripheralJobAdded((PeripheralJob) evt.getCurrentOrPreviousObjectState());
          break;
        case OBJECT_MODIFIED:
          peripheralJobChanged((PeripheralJob) evt.getCurrentOrPreviousObjectState());
          break;
        case OBJECT_REMOVED:
          peripheralJobRemoved((PeripheralJob) evt.getCurrentOrPreviousObjectState());
          break;
        default:
          LOG.warn("Unhandled event type: {}", evt.getType());
      }
    }
  }

  private void peripheralJobAdded(PeripheralJob job) {
    peripheralJobs.put(job.getName(), job);
    listeners.forEach(listener -> listener.peripheralJobAdded(job));
  }

  private void peripheralJobChanged(PeripheralJob job) {
    peripheralJobs.put(job.getName(), job);
    listeners.forEach(listener -> listener.peripheralJobUpdated(job));
  }

  private void peripheralJobRemoved(PeripheralJob job) {
    peripheralJobs.remove(job.getName());
    listeners.forEach(listener -> listener.peripheralJobRemoved(job));
  }

  private void setPeripheralJobs(Set<PeripheralJob> newJobs) {
    peripheralJobs.clear();
    for (PeripheralJob job : newJobs) {
      peripheralJobs.put(job.getName(), job);
    }
  }

  private Set<PeripheralJob> fetchJobsIfOnline() {
    if (portalProvider.portalShared()) {
      try (SharedKernelServicePortal sharedPortal = portalProvider.register()) {
        return sharedPortal.getPortal().getPeripheralJobService().fetchObjects(PeripheralJob.class);
      }
      catch (KernelRuntimeException exc) {
        LOG.warn("Exception fetching peripheral jobs", exc);
      }
    }

    return new HashSet<>();
  }
}


<|start_filename|>openTCS-Kernel-Extension-Statistics/src/main/java/org/opentcs/kernel/extensions/statistics/StatisticsCollector.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.statistics;

import java.io.File;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.KernelExtension;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.ApplicationHome;
import static org.opentcs.util.Assertions.checkArgument;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Collects data from kernel events and logs interesting events to a file that
 * can later be processed for statistical purposes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatisticsCollector
    implements KernelExtension {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StatisticsCollector.class);
  /**
   * Where we register for application events.
   */
  private final EventSource eventSource;
  /**
   * The directory to log event data to.
   */
  private final File logDir;
  /**
   * Whether this instance is currently initialized.
   */
  private boolean initialized;
  /**
   * An event logger for persisting the event data collected.
   */
  private StatisticsEventLogger statisticsLogger;

  /**
   * Creates a new instance.
   *
   * @param eventSource Where this instance registers for application events.
   * @param homeDir The kernel's home directory.
   */
  @Inject
  public StatisticsCollector(@ApplicationEventBus EventSource eventSource,
                             @ApplicationHome File homeDir) {
    this.eventSource = requireNonNull(eventSource, "eventSource");
    requireNonNull(homeDir, "homeDir");
    this.logDir = new File(homeDir, "log/statistics");
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    checkArgument(logDir.isDirectory() || logDir.mkdirs(),
                  "Directory %s does not exist and could not be created, either.",
                  logDir.getPath());
    Format format = new SimpleDateFormat("yyyyMMdd-HHmmss");
    File logFile = new File(logDir, "opentcs-statistics-" + format.format(new Date()) + ".txt");

    // Create event processor and register it for kernel events.
    LOG.info("Logging events to {}...", logFile.getAbsolutePath());
    statisticsLogger = new StatisticsEventLogger(logFile);
    statisticsLogger.initialize();
    eventSource.subscribe(statisticsLogger);

    // Remember we're plugged in.
    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    // Unregister event listener, terminate event processing.
    eventSource.unsubscribe(statisticsLogger);
    statisticsLogger.terminate();

    statisticsLogger = null;
    initialized = false;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/package-info.java<|end_filename|>
/**
 * Transfer object classes for plant model objects.
 */
package org.opentcs.access.to.model;


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/messages/SetSpeedMultiplier.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle.messages;

import java.io.Serializable;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * A message that informs a communication adapter about a speed multiplier it/the vehicle should
 * apply.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetSpeedMultiplier
    implements Serializable {

  /**
   * The speed multiplier in percent.
   */
  private final int multiplier;

  /**
   * Creates a new instance.
   *
   * @param multiplier The speed multiplier in percent.
   */
  public SetSpeedMultiplier(final int multiplier) {
    this.multiplier = checkInRange(multiplier, 0, 100, "multiplier");
  }

  /**
   * Returns the speed multiplier in percent.
   *
   * @return The speed multiplier in percent.
   */
  public int getMultiplier() {
    return multiplier;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/LowLevelCommunicationEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers;

import java.io.Serializable;

/**
 * Marks low-level communication events.
 * Can be used e.g. to distinguish low-level events that are meant for component-internal processing
 * and that are irrelevant for high-level UI visualization.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LowLevelCommunicationEvent
    extends Serializable {

}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/menus/menubar/ViewMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
import org.jhotdraw.app.action.window.ToggleVisibleAction;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.application.action.ToolBarManager;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.action.view.AddBitmapAction;
import org.opentcs.guing.application.action.view.RestoreDockingLayoutAction;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's menu for view-related operations.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewMenu
    extends JMenu {

  /**
   * The toolbar manager.
   */
  private final ToolBarManager toolBarManager;
  /**
   * A menu item for setting a bitmap for the current drawing view.
   */
  private final JMenuItem menuAddBitmap;
  /**
   * A menu for manipulating the application's tool bars.
   */
  private final ViewToolBarsMenu menuViewToolBars;
  /**
   * A menu for showing/hiding plugin panels.
   */
  private final ViewPluginPanelsMenu menuPluginPanels;
  /**
   * A menu item for restoring the default GUI layout.
   */
  private final JMenuItem menuItemRestoreDockingLayout;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   * @param toolBarManager The toolbar manager.
   * @param menuPluginPanels A menu for showing/hiding plugin panels.
   */
  @Inject
  public ViewMenu(ViewActionMap actionMap,
                  ToolBarManager toolBarManager,
                  ViewPluginPanelsMenu menuPluginPanels) {
    requireNonNull(actionMap, "actionMap");
    this.toolBarManager = requireNonNull(toolBarManager, "toolBarManager");
    requireNonNull(menuPluginPanels, "menuPluginPanels");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH);

    this.setText(labels.getString("viewMenu.text"));
    this.setToolTipText(labels.getString("viewMenu.tooltipText"));
    this.setMnemonic('V');

    // Menu item View -> Add Background Image
    menuAddBitmap = new JMenuItem(actionMap.get(AddBitmapAction.ID));
    add(menuAddBitmap);

    addSeparator();

    List<Action> viewActions = createToolBarActions();
    if (!viewActions.isEmpty()) {
      menuViewToolBars = new ViewToolBarsMenu(viewActions);
      add(menuViewToolBars);
    }
    else {
      menuViewToolBars = null;
    }

    // Menu item View -> Plugins
    this.menuPluginPanels = menuPluginPanels;
    menuPluginPanels.setOperationMode(OperationMode.MODELLING);
    add(menuPluginPanels);

    // Menu item View -> Restore docking layout
    menuItemRestoreDockingLayout = new JMenuItem(actionMap.get(RestoreDockingLayoutAction.ID));
    menuItemRestoreDockingLayout.setText(labels.getString("viewMenu.menuItem_restoreWindowArrangement.text"));
    add(menuItemRestoreDockingLayout);
  }

  private List<Action> createToolBarActions() {
    List<Action> toolBarActions = new ArrayList<>();
    for (JToolBar curToolBar : toolBarManager.getToolBars()) {
      toolBarActions.add(new ToggleVisibleAction(curToolBar, curToolBar.getName()));
    }
    return toolBarActions;
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/V003PlantModelTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.opentcs.util.persistence.BasePlantModelTO;
import org.xml.sax.SAXException;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlRootElement(name = "model")
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"version", "name", "points", "paths", "vehicles", "locationTypes",
                      "locations", "blocks", "groups", "visualLayouts", "properties"})
public class V003PlantModelTO
    extends BasePlantModelTO {

  private String name = "";
  private List<PointTO> points = new ArrayList<>();
  private List<PathTO> paths = new ArrayList<>();
  private List<VehicleTO> vehicles = new ArrayList<>();
  private List<LocationTypeTO> locationTypes = new ArrayList<>();
  private List<LocationTO> locations = new ArrayList<>();
  private List<BlockTO> blocks = new ArrayList<>();
  private List<GroupTO> groups = new ArrayList<>();
  private List<VisualLayoutTO> visualLayouts = new ArrayList<>();
  private List<PropertyTO> properties = new ArrayList<>();

  @XmlAttribute(required = true)
  public String getName() {
    return name;
  }

  public V003PlantModelTO setName(@Nonnull String name) {
    requireNonNull(name, "name");
    this.name = name;
    return this;
  }

  @XmlElement(name = "point")
  public List<PointTO> getPoints() {
    return points;
  }

  public V003PlantModelTO setPoints(@Nonnull List<PointTO> points) {
    requireNonNull(points, "points");
    this.points = points;
    return this;
  }

  @XmlElement(name = "path")
  public List<PathTO> getPaths() {
    return paths;
  }

  public V003PlantModelTO setPaths(@Nonnull List<PathTO> paths) {
    requireNonNull(paths, "paths");
    this.paths = paths;
    return this;
  }

  @XmlElement(name = "vehicle")
  public List<VehicleTO> getVehicles() {
    return vehicles;
  }

  public V003PlantModelTO setVehicles(@Nonnull List<VehicleTO> vehicles) {
    requireNonNull(vehicles, "vehicles");
    this.vehicles = vehicles;
    return this;
  }

  @XmlElement(name = "locationType")
  public List<LocationTypeTO> getLocationTypes() {
    return locationTypes;
  }

  public V003PlantModelTO setLocationTypes(@Nonnull List<LocationTypeTO> locationTypes) {
    requireNonNull(locationTypes, "locationTypes");
    this.locationTypes = locationTypes;
    return this;
  }

  @XmlElement(name = "location")
  public List<LocationTO> getLocations() {
    return locations;
  }

  public V003PlantModelTO setLocations(@Nonnull List<LocationTO> locations) {
    requireNonNull(locations, "locations");
    this.locations = locations;
    return this;
  }

  @XmlElement(name = "block")
  public List<BlockTO> getBlocks() {
    return blocks;
  }

  public V003PlantModelTO setBlocks(@Nonnull List<BlockTO> blocks) {
    requireNonNull(blocks, "blocks");
    this.blocks = blocks;
    return this;
  }

  @XmlElement(name = "group")
  public List<GroupTO> getGroups() {
    return groups;
  }

  public V003PlantModelTO setGroups(@Nonnull List<GroupTO> groups) {
    requireNonNull(groups, "groups");
    this.groups = groups;
    return this;
  }

  @XmlElement(name = "visualLayout")
  public List<VisualLayoutTO> getVisualLayouts() {
    return visualLayouts;
  }

  public V003PlantModelTO setVisualLayouts(@Nonnull List<VisualLayoutTO> visualLayouts) {
    requireNonNull(visualLayouts, "visualLayouts");
    this.visualLayouts = visualLayouts;
    return this;
  }

  @XmlElement(name = "property")
  public List<PropertyTO> getProperties() {
    return properties;
  }

  public V003PlantModelTO setProperties(@Nonnull List<PropertyTO> properties) {
    requireNonNull(properties, "properties");
    this.properties = properties;
    return this;
  }

  /**
   * Marshals this instance to its XML representation and writes it to the given writer.
   *
   * @param writer The writer to write this instance's XML representation to.
   * @throws IOException If there was a problem marshalling this instance.
   */
  public void toXml(@Nonnull Writer writer)
      throws IOException {
    requireNonNull(writer, "writer");

    try {
      createMarshaller().marshal(this, writer);
    }
    catch (JAXBException | SAXException exc) {
      throw new IOException("Exception marshalling data", exc);
    }
  }

  /**
   * Unmarshals an instance of this class from the given XML representation.
   *
   * @param reader Provides the XML representation to parse to an instance.
   * @return The instance unmarshalled from the given reader.
   * @throws IOException If there was a problem unmarshalling the given string.
   */
  public static V003PlantModelTO fromXml(@Nonnull Reader reader)
      throws IOException {
    requireNonNull(reader, "reader");

    try {
      return (V003PlantModelTO) createUnmarshaller().unmarshal(reader);
    }
    catch (JAXBException | SAXException exc) {
      throw new IOException("Exception unmarshalling data", exc);
    }
  }

  private static Marshaller createMarshaller()
      throws JAXBException, SAXException {
    Marshaller marshaller = createContext().createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    marshaller.setSchema(createSchema());
    return marshaller;
  }

  private static Unmarshaller createUnmarshaller()
      throws JAXBException, SAXException {
    Unmarshaller unmarshaller = createContext().createUnmarshaller();
    unmarshaller.setSchema(createSchema());
    return unmarshaller;
  }

  private static JAXBContext createContext()
      throws JAXBException {
    return JAXBContext.newInstance(V003PlantModelTO.class);
  }

  private static Schema createSchema()
      throws SAXException {
    URL schemaUrl = V003PlantModelTO.class.getResource("/org/opentcs/util/persistence/model-0.0.3.xsd");
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    return schemaFactory.newSchema(schemaUrl);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/AssignmentState.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;

/**
 * The result of trying to assign a set of vehicles/transport orders.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignmentState {

  private final List<AssignmentCandidate> assignedCandidates = new ArrayList<>();
  private final List<AssignmentCandidate> reservedCandidates = new ArrayList<>();
  private final Map<TransportOrder, OrderFilterResult> filteredOrders = new HashMap<>();

  public AssignmentState() {
  }

  public List<AssignmentCandidate> getAssignedCandidates() {
    return assignedCandidates;
  }

  public List<AssignmentCandidate> getReservedCandidates() {
    return reservedCandidates;
  }

  public Map<TransportOrder, OrderFilterResult> getFilteredOrders() {
    return filteredOrders;
  }

  public void addFilteredOrder(OrderFilterResult filterResult) {
    TransportOrder order = filterResult.getOrder();
    OrderFilterResult result = filteredOrders.getOrDefault(order,
                                                      new OrderFilterResult(order, new ArrayList<>()));
    result.getFilterReasons().addAll(filterResult.getFilterReasons());
    filteredOrders.put(order, result);
  }

  /**
   * Checks whether the given transport order is still assignable, taking into account the current
   * assignment results.
   *
   * @param order The transport order to check.
   * @return {@code true}, if the given transport order was not yet assigned or reserved, otherwise
   * {@code false}.
   */
  public boolean wasAssignedToVehicle(TransportOrder order) {
    return Stream.concat(assignedCandidates.stream(), reservedCandidates.stream())
        .anyMatch(candidate -> Objects.equals(candidate.getTransportOrder(), order));
  }

  /**
   * Checks whether the given vehicle is still assignable, taking into account the current
   * assignment results.
   *
   * @param vehicle The vehicle to check.
   * @return {@code true}, if a transport order was not yet assigned to or reserved for the given
   * vehicle, otherwise {@code false}.
   */
  public boolean wasAssignedToOrder(Vehicle vehicle) {
    return Stream.concat(assignedCandidates.stream(), reservedCandidates.stream())
        .anyMatch(candidate -> Objects.equals(candidate.getVehicle(), vehicle));
  }
  
  public boolean wasFiltered(TransportOrder order) {
    return filteredOrders.containsKey(order);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/menus/menubar/FileMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.action.file.ModelPropertiesAction;
import org.opentcs.guing.application.action.file.SaveModelAction;
import org.opentcs.guing.application.action.file.SaveModelAsAction;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.thirdparty.jhotdraw.application.action.file.CloseFileAction;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's "File" menu.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FileMenu
    extends JMenu {

  /**
   * A menu item for persisting the kernel's current model.
   */
  private final JMenuItem menuItemSaveModel;
  /**
   * A menu item for persisting the kernel's current model with a new name.
   */
  private final JMenuItem menuItemSaveModelAs;
  /**
   * A menu item for showing the current model's properties.
   */
  private final JMenuItem menuItemModelProperties;
  /**
   * A menu item for closing the application.
   */
  private final JMenuItem menuItemClose;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   */
  @Inject
  public FileMenu(ViewActionMap actionMap) {
    requireNonNull(actionMap, "actionMap");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.MENU_PATH);
    
    this.setText( labels.getString("fileMenu.text"));
    this.setToolTipText(labels.getString("fileMenu.tooltipText"));
    this.setMnemonic('F');

    // Menu item File -> Save Model
    menuItemSaveModel = new JMenuItem(actionMap.get(SaveModelAction.ID));
    add(menuItemSaveModel);

    // Menu item File -> Save Model As
    menuItemSaveModelAs = new JMenuItem(actionMap.get(SaveModelAsAction.ID));
    add(menuItemSaveModelAs);

    addSeparator();

    menuItemModelProperties = new JMenuItem(actionMap.get(ModelPropertiesAction.ID));
    add(menuItemModelProperties);

    addSeparator();

    // Menu item File -> Close
    menuItemClose = new JMenuItem(actionMap.get(CloseFileAction.ID));
    add(menuItemClose); // TODO: Nur bei "Stand-Alone" Frame
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/event/EventHandler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.event;

/**
 * A handler for events emitted by an {@link EventSource}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface EventHandler {

  /**
   * Processes the event object.
   *
   * @param event The event object.
   */
  void onEvent(Object event);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/util/UniqueNameGenerator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import javax.inject.Inject;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.util.UniqueStringGenerator;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class UniqueNameGenerator
    extends UniqueStringGenerator<Class<? extends ModelComponent>> {

  @Inject
  public UniqueNameGenerator(ElementNamingSchemeConfiguration config) {
    registerNamePattern(PointModel.class, config.pointPrefix(), config.pointNumberPattern());
    registerNamePattern(PathModel.class, config.pathPrefix(), config.pathNumberPattern());
    registerNamePattern(LocationTypeModel.class, config.locationTypePrefix(), config.locationTypeNumberPattern());
    registerNamePattern(LocationModel.class, config.locationPrefix(), config.locationNumberPattern());
    registerNamePattern(LinkModel.class, config.linkPrefix(), config.linkNumberPattern());
    registerNamePattern(BlockModel.class, config.blockPrefix(), config.blockNumberPattern());
    registerNamePattern(LayoutModel.class, config.layoutPrefix(), config.layoutNumberPattern());
    registerNamePattern(VehicleModel.class, config.vehiclePrefix(), config.vehicleNumberPattern());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/management/package-info.java<|end_filename|>
/**
 * Components needed for processing information related to peripheral comm adapters.
 */
package org.opentcs.drivers.peripherals.management;


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/ProbePlantModelTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence;

import java.io.IOException;
import java.io.Reader;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.xml.sax.SAXException;

/**
 * Allows reading a model file to access basic information (such as the model version) for
 * validation purposes.
 * 
 * @author <NAME> (Fraunhofer IML)
 */
@XmlRootElement(name = "model")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class ProbePlantModelTO
    extends BasePlantModelTO {

  /**
   * Unmarshals an instance of this class from the given XML representation.
   *
   * @param reader Provides the XML representation to parse to an instance.
   * @return The instance unmarshalled from the given reader.
   * @throws IOException If there was a problem unmarshalling the given string.
   */
  public static ProbePlantModelTO fromXml(@Nonnull Reader reader)
      throws IOException {
    requireNonNull(reader, "reader");

    try {
      return (ProbePlantModelTO) createUnmarshaller().unmarshal(reader);
    }
    catch (JAXBException | SAXException exc) {
      throw new IOException("Exception unmarshalling data", exc);
    }
  }

  private static Unmarshaller createUnmarshaller()
      throws JAXBException, SAXException {
    Unmarshaller unmarshaller = createContext().createUnmarshaller();
    return unmarshaller;
  }

  private static JAXBContext createContext()
      throws JAXBException {
    return JAXBContext.newInstance(ProbePlantModelTO.class);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/KernelServicePortalBuilder.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi;

import static java.util.Objects.requireNonNull;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import org.opentcs.access.CredentialsException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.rmi.factories.NullSocketFactoryProvider;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.access.rmi.services.RemoteKernelServicePortalProxy;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.util.ClassMatcher;

/**
 * Builds {@link KernelServicePortal} instances for connections to remote portals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class KernelServicePortalBuilder {

  /**
   * Provides socket factories used for RMI.
   */
  private SocketFactoryProvider socketFactoryProvider = new NullSocketFactoryProvider();
  /**
   * The user name for logging in.
   */
  private final String userName;
  /**
   * The password for logging in.
   */
  private final String password;
  /**
   * The event filter to be applied for the built portal.
   */
  private Predicate<Object> eventFilter = new ClassMatcher(Object.class);

  /**
   * Creates a new instance.
   *
   * @param userName The user name to use for logging in.
   * @param password The password to use for logging in.
   */
  public KernelServicePortalBuilder(String userName, String password) {
    this.userName = requireNonNull(userName, "userName");
    this.password = requireNonNull(password, "password");
  }

  /**
   * Returns the socket factory provider used for RMI.
   *
   * @return The socket factory provider used for RMI.
   */
  public SocketFactoryProvider getSocketFactoryProvider() {
    return socketFactoryProvider;
  }

  /**
   * Sets the socket factory provider used for RMI.
   *
   * @param socketFactoryProvider The socket factory provider.
   * @return This instance.
   */
  public KernelServicePortalBuilder setSocketFactoryProvider(
      @Nonnull SocketFactoryProvider socketFactoryProvider) {
    this.socketFactoryProvider = requireNonNull(socketFactoryProvider, "socketFactoryProvider");
    return this;
  }

  /**
   * Returns the user name used for logging in.
   *
   * @return The user name used for logging in.
   */
  public String getUserName() {
    return userName;
  }

  /**
   * Returns the password used for logging in.
   *
   * @return The password used for logging in.
   */
  public String getPassword() {
    return password;
  }

  /**
   * Returns the event filter to be applied for the built portal.
   *
   * @return The event filter to be applied for the built portal.
   */
  public Predicate<Object> getEventFilter() {
    return eventFilter;
  }

  /**
   * Sets the event filter to be applied for the built portal.
   *
   * @param eventFilter The event filter.
   * @return This instance.
   */
  public KernelServicePortalBuilder setEventFilter(@Nonnull Predicate<Object> eventFilter) {
    this.eventFilter = requireNonNull(eventFilter, "eventFilter");
    return this;
  }

  /**
   * Builds and returns a {@link KernelServicePortal} with the configured parameters.
   *
   * @return A {@link KernelServicePortal} instance.
   * @throws ServiceUnavailableException If the remote portal is not reachable for some reason.
   * @throws CredentialsException If the client login with the remote portal failed, e.g. because of
   * incorrect login data.
   */
  public KernelServicePortal build()
      throws ServiceUnavailableException, CredentialsException {
    RemoteKernelServicePortalProxy portal = new RemoteKernelServicePortalProxy(
        userName,
        password,
        socketFactoryProvider,
        eventFilter);
    return portal;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/package-info.java<|end_filename|>
/**
 * Interfaces and classes for transparently providing an openTCS kernel's service functionality via
 * RMI.
 */
package org.opentcs.access.rmi.services;


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/persistence/ModelManagerModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence;

import java.io.File;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.components.plantoverview.PlantModelExporter;
import org.opentcs.components.plantoverview.PlantModelImporter;

/**
 * Manages (loads, saves and keeps) the driving course model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ModelManagerModeling
    extends ModelManager {

  /**
   * Shows a dialog to select a model and loads it.
   *
   * @param modelFile The nullable model file to be loaded. If it
   * is not present a dialog to select a file will be shown.
   * @return <code>true</code> if, and only if, a model was successfully
   * loaded.
   */
  boolean loadModel(@Nullable File modelFile);

  /**
   * Shows a dialog to select a model and loads it.
   *
   * @param modelFile The nullable model file to be loaded. If it
   * is not present a dialog to select a file will be shown.
   * @param reader The reader which reads and parses the file.
   * @return <code>true</code> if, and only if, a model was successfully
   * loaded.
   */
  boolean loadModel(@Nullable File modelFile, ModelFileReader reader);

  /**
   * Imports a model using the given importer.
   *
   * @param importer The importer to be used.
   * @return <code>true</code> if, and only if, a model was successfully imported.
   */
  boolean importModel(@Nonnull PlantModelImporter importer);

  /**
   * Uploads the given system model to the kernel.
   *
   * @param portal The kernel client portal to upload the model to.
   * @return Whether the model was actually uploaded.
   */
  boolean uploadModel(KernelServicePortal portal);

  /**
   * Exports a model using the given exporter.
   *
   * @param exporter The exporter to be used.
   * @return <code>true</code> if, and only if, the model was successfully exported.
   */
  boolean exportModel(@Nonnull PlantModelExporter exporter);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/CompositeOrderComparator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization;

import com.google.common.collect.Lists;
import java.util.Comparator;
import java.util.Map;
import javax.inject.Inject;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorByAge;
import org.opentcs.strategies.basic.dispatching.priorization.transportorder.TransportOrderComparatorByName;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A composite of all configured transport order comparators.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeOrderComparator
    implements Comparator<TransportOrder> {

  /**
   * A comparator composed of all configured comparators, in the configured order.
   */
  private final Comparator<TransportOrder> compositeComparator;

  @Inject
  public CompositeOrderComparator(DefaultDispatcherConfiguration configuration,
                                  Map<String, Comparator<TransportOrder>> availableComparators) {
    // At the end, if all other comparators failed to see a difference, compare by age.
    // As the age of two distinct transport orders may still be the same, finally compare by name.
    // Add configured comparators before these two.
    Comparator<TransportOrder> composite
        = new TransportOrderComparatorByAge().thenComparing(new TransportOrderComparatorByName());

    for (String priorityKey : Lists.reverse(configuration.orderPriorities())) {
      Comparator<TransportOrder> configuredComparator = availableComparators.get(priorityKey);
      checkArgument(configuredComparator != null, "Unknown order priority key: %s", priorityKey);
      composite = configuredComparator.thenComparing(composite);
    }
    this.compositeComparator = composite;
  }

  @Override
  public int compare(TransportOrder o1, TransportOrder o2) {
    return compositeComparator.compare(o1, o2);
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/AbstractParkingPositionSupplier.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.Collections;
import java.util.Comparator;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;

/**
 * An abstract base class for parking position suppliers.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractParkingPositionSupplier
    implements ParkingPositionSupplier {

  /**
   * The plant model service.
   */
  private final InternalPlantModelService plantModelService;
  /**
   * A router for computing distances to parking positions.
   */
  private final Router router;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param plantModelService The plant model service.
   * @param router A router for computing distances to parking positions.
   */
  protected AbstractParkingPositionSupplier(InternalPlantModelService plantModelService,
                                            Router router) {
    this.plantModelService = requireNonNull(plantModelService, "plantModelService");
    this.router = requireNonNull(router, "router");
  }

  @Override
  public void initialize() {
    if (initialized) {
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!initialized) {
      return;
    }

    initialized = false;
  }

  /**
   * Returns the plant model service.
   *
   * @return The plant model service.
   */
  public InternalPlantModelService getPlantModelService() {
    return plantModelService;
  }

  /**
   * Returns the system's router.
   *
   * @return The system's router.
   */
  public Router getRouter() {
    return router;
  }

  /**
   * Returns a set of parking positions usable for the given vehicle (usable in the sense that these
   * positions are not occupied by other vehicles).
   *
   * @param vehicle The vehicles to find parking positions for.
   * @return The set of usable parking positions.
   */
  protected Set<Point> findUsableParkingPositions(Vehicle vehicle) {
    // Find out which points are destination points of the current routes of
    // all vehicles, and keep them. (Multiple lookups ahead.)
    Set<Point> targetedPoints = getRouter().getTargetedPoints();

    return fetchAllParkingPositions().stream()
        .filter(point -> isPointUnoccupiedFor(point, vehicle, targetedPoints))
        .collect(Collectors.toSet());
  }

  /**
   * Returns from the given set of points the one that is nearest to the given
   * vehicle.
   *
   * @param vehicle The vehicle.
   * @param points The set of points to select the nearest one from.
   * @return The point nearest to the given vehicle.
   */
  @Nullable
  protected Point nearestPoint(Vehicle vehicle, Set<Point> points) {
    requireNonNull(vehicle, "vehicle");
    requireNonNull(points, "points");

    if (vehicle.getCurrentPosition() == null) {
      return null;
    }

    Point vehiclePos = plantModelService.fetchObject(Point.class, vehicle.getCurrentPosition());

    return points.stream()
        .map(point -> parkingPositionCandidate(vehicle, vehiclePos, point))
        .filter(candidate -> candidate.costs < Long.MAX_VALUE)
        .min(Comparator.comparingLong(candidate -> candidate.costs))
        .map(candidate -> candidate.point)
        .orElse(null);
  }

  /**
   * Gathers a set of all points from all blocks that the given point is a member of.
   *
   * @param point The point to check.
   * @return A set of all points from all blocks that the given point is a member of.
   */
  protected Set<Point> expandPoints(Point point) {
    return plantModelService.expandResources(Collections.singleton(point.getReference())).stream()
        .filter(resource -> Point.class.equals(resource.getReference().getReferentClass()))
        .map(resource -> (Point) resource)
        .collect(Collectors.toSet());
  }

  protected Set<Point> fetchAllParkingPositions() {
    return plantModelService.fetchObjects(Point.class, point -> point.isParkingPosition());
  }

  /**
   * Checks if ALL points within the same block as the given access point are NOT occupied or
   * targeted by any other vehicle than the given one.
   *
   * @param accessPoint The point to be checked.
   * @param vehicle The vehicle to be checked for.
   * @param targetedPoints All currently known targeted points.
   * @return <code>true</code> if, and only if, ALL points within the same block as the given access
   * point are NOT occupied or targeted by any other vehicle than the given one.
   */
  private boolean isPointUnoccupiedFor(Point accessPoint,
                                       Vehicle vehicle,
                                       Set<Point> targetedPoints) {
    return expandPoints(accessPoint).stream()
        .allMatch(point -> !pointOccupiedOrTargetedByOtherVehicle(point,
                                                                  vehicle,
                                                                  targetedPoints));
  }

  private boolean pointOccupiedOrTargetedByOtherVehicle(Point pointToCheck,
                                                        Vehicle vehicle,
                                                        Set<Point> targetedPoints) {
    if (pointToCheck.getOccupyingVehicle() != null
        && !pointToCheck.getOccupyingVehicle().equals(vehicle.getReference())) {
      return true;
    }
    else if (targetedPoints.contains(pointToCheck)) {
      return true;
    }
    return false;
  }

  private PointCandidate parkingPositionCandidate(Vehicle vehicle,
                                                  Point srcPosition,
                                                  Point destPosition) {
    return new PointCandidate(destPosition, router.getCosts(vehicle, srcPosition, destPosition));
  }

  private static class PointCandidate {

    private final Point point;
    private final long costs;

    public PointCandidate(Point point, long costs) {
      this.point = point;
      this.costs = costs;
    }
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/logging/SingleLineFormatter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.logging;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

/**
 * A <code>Formatter</code> for <code>LogRecord</code>s that formats messages
 * for output on a single line (except when a <code>Throwable</code> is
 * associated with the <code>LogRecord</code>.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SingleLineFormatter
    extends Formatter {

  /**
   * A <code>DateFormat</code> instance for formatting timestamps.
   */
  private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd-HH:mm:ss-SSS");
  /**
   * A <code>Date</code> instance for formatting timestamps.
   */
  private final Date date = new Date();
  /**
   * Line separator for wrapping lines at the end of log messages.
   */
  private final String lineSeparator = System.getProperty("line.separator");

  /**
   * Creates a new SingleLineFormatter.
   */
  public SingleLineFormatter() {
  }

  @Override
  public synchronized String format(LogRecord record) {
    date.setTime(record.getMillis());
    StringBuilder result = new StringBuilder();

    result.append('[')
        .append(DATE_FORMAT.format(date))
        .append("] ")
        .append(String.format("%1$-7.7s", record.getLevel().getName()))
        .append(' ')
        .append(String.format("%1$-20s", Thread.currentThread().getName()))
        .append(' ')
        .append(String.format("%1$-55s", source(record)))
        .append(": ")
        .append(formatMessage(record))
        .append(lineSeparator);

    if (record.getThrown() != null) {
      result.append(stackTrace(record.getThrown()));
      result.append(lineSeparator);
    }

    return result.toString();
  }

  private String source(LogRecord record) {
    return record.getSourceClassName() != null
        ? record.getSourceClassName().replaceAll("\\B\\w+(\\.[a-z])", "$1") + "." + record.getSourceMethodName() + "()"
        : record.getLoggerName();
  }

  private String stackTrace(Throwable thrown) {
    try (StringWriter sWriter = new StringWriter();
         PrintWriter pWriter = new PrintWriter(sWriter)) {
      thrown.printStackTrace(pWriter);
      pWriter.flush();
      return sWriter.toString();
    }
    catch (IOException exc) {
      throw new IllegalStateException("Could not print stack trace for log output", exc);
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/PeripheralReleaseStrategy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import java.util.Collection;
import org.opentcs.data.model.Location;

/**
 * A strategy that determines peripherals whose reservations are to be released.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralReleaseStrategy {

  /**
   * Selects the peripherals whose reservations are to be released.
   *
   * @param locations The peripherals to select from.
   * @return The selected peripherals.
   */
  Collection<Location> selectPeripheralsToRelease(Collection<Location> locations);
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/FileSystems.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.io.File;
import static java.util.Objects.requireNonNull;

/**
 * This class provides helper methods for working with file systems.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class FileSystems {

  /**
   * Prevents creation of instances.
   */
  private FileSystems() {
  }

  /**
   * Recursively deletes a given file/directory.
   *
   * @param target The file/directory to be deleted recursively.
   * @return <code>true</code> if deleting the target was successful, else
   * <code>false</code>.
   */
  public static boolean deleteRecursively(File target) {
    requireNonNull(target, "target");

    // If the target is a directory, remove its contents first.
    if (target.isDirectory()) {
      File[] entries = target.listFiles();
      for (File curEntry : entries) {
        boolean successful;

        if (curEntry.isDirectory()) {
          successful = deleteRecursively(curEntry);
        }
        else {
          successful = curEntry.delete();
        }

        if (!successful) {
          return false;
        }
      }
    }

    return target.delete();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/dialogs/DialogContent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dialogs;

import javax.swing.JComponent;
import javax.swing.JPanel;

/**
 * Base implementation for a dialog and tab content.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class DialogContent
    extends JPanel {

  /**
   * Title of the component in a dialog.
   */
  protected String fDialogTitle;
  /**
   * Title of the component in a tab.
   */
  protected String fTabTitle;
  /**
   * Indicates that the update of the value has failed.
   */
  protected boolean updateFailed;
  /**
   * Whether or not this dialog is modal.
   */
  protected boolean fModal;
  /**
   * Parent dialog where this content is added to.
   */
  protected StandardContentDialog fDialog;

  /**
   * Creates a new instance of AbstractDialogContent.
   */
  public DialogContent() {
    setModal(true);
  }

  /**
   * Returns the component.
   *
   * @return The component of this dialog.
   */
  public JComponent getComponent() {
    return this;
  }

  /**
   * Sets the dialog to be modal.
   *
   * @param modal true if the dialog should be modal.
   */
  public final void setModal(boolean modal) {
    fModal = modal;
  }

  /**
   * Returns whether or not the component is modal.
   * 
   * @return Whether or not the component is modal.
   */
  public boolean getModal() {
    return fModal;
  }

  /**
   * Returns the title for a tab.
   *
   * @return The title for a tab.
   */
  public String getTabTitle() {
    return fTabTitle;
  }

  /**
   * Returns the title for a dialog.
   *
   * @return The title for a dialog.
   */
  public String getDialogTitle() {
    return fDialogTitle;
  }

  /**
   * Set the title for a dialog.
   *
   * @param title The new title for a dialog.
   */
  protected void setDialogTitle(String title) {
    fDialogTitle = title;
  }

  /**
   * Set the title for a tab.
   *
   * @param title The new title for a tab.
   */
  protected void setTabTitle(String title) {
    fTabTitle = title;
  }

  /**
   * Notifies the registered listeners that the dialog would like to close.
   */
  protected void notifyRequestClose() {
    fDialog.requestClose();
  }

  /**
   * Returns whether or not the update of the UI elements failed.
   *
   * @return true if the update failed.
   */
  public boolean updateFailed() {
    return updateFailed;
  }

  /**
   * Initialises the dialog elements.
   */
  public abstract void initFields();

  /**
   * Updates the values from the dialog elements.
   */
  public abstract void update();
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/V003ModelParser.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import java.io.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.opentcs.util.persistence.v002.V002ModelParser;
import org.opentcs.util.persistence.v002.V002PlantModelTO;

/**
 * The parser for V003 models.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V003ModelParser {

  /**
   * The file format version this parser works with.
   */
  public static final String VERSION_STRING = "0.0.3";

  /**
   * Reads a model with the given reader and parses it to a {@link V003PlantModelTO} instance.
   *
   * @param reader The reader to use.
   * @param modelVersion The model version.
   * @return The parsed {@link V003PlantModelTO}.
   * @throws IOException If there was an error reading the model.
   */
  public V003PlantModelTO readRaw(Reader reader, String modelVersion)
      throws IOException {
    if (Objects.equals(modelVersion, VERSION_STRING)) {
      return V003PlantModelTO.fromXml(reader);
    }
    else {
      return convert(new V002ModelParser().readRaw(reader, modelVersion));
    }
  }

  private V003PlantModelTO convert(V002PlantModelTO to) {
    return new V003PlantModelTO()
        .setName(to.getName())
        .setPoints(convertPoints(to))
        .setPaths(convertPaths(to))
        .setVehicles(convertVehicles(to))
        .setLocationTypes(convertLocationTypes(to))
        .setLocations(convertLocations(to))
        .setBlocks(convertBlocks(to))
        .setGroups(convertGroups(to))
        .setVisualLayouts(convertVisualLayouts(to))
        .setProperties(convertProperties(to.getProperties()));
  }

  private List<PointTO> convertPoints(V002PlantModelTO to) {
    return to.getPoints().stream()
        .map(point -> {
          PointTO result = new PointTO();
          result.setName(point.getName())
              .setProperties(convertProperties(point.getProperties()));
          result.setxPosition(point.getxPosition())
              .setyPosition(point.getyPosition())
              .setzPosition(point.getzPosition())
              .setVehicleOrientationAngle(point.getVehicleOrientationAngle())
              .setType(point.getType())
              .setOutgoingPaths(convertOutgoingPaths(point));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<PropertyTO> convertProperties(
      List<org.opentcs.util.persistence.v002.PropertyTO> tos) {
    return tos.stream()
        .map(property -> new PropertyTO().setName(property.getName()).setValue(property.getValue()))
        .collect(Collectors.toList());
  }

  private List<PointTO.OutgoingPath> convertOutgoingPaths(
      org.opentcs.util.persistence.v002.PointTO to) {
    return to.getOutgoingPaths().stream()
        .map(path -> new PointTO.OutgoingPath().setName(path.getName()))
        .collect(Collectors.toList());
  }

  private List<PathTO> convertPaths(V002PlantModelTO to) {
    return to.getPaths().stream()
        .map(path -> {
          PathTO result = new PathTO();
          result.setName(path.getName())
              .setProperties(convertProperties(path.getProperties()));
          result.setSourcePoint(path.getSourcePoint())
              .setDestinationPoint(path.getDestinationPoint())
              .setLength(path.getLength())
              .setMaxVelocity(path.getMaxVelocity())
              .setMaxReverseVelocity(path.getMaxReverseVelocity())
              .setLocked(path.isLocked());
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<VehicleTO> convertVehicles(V002PlantModelTO to) {
    return to.getVehicles().stream()
        .map(vehicle -> {
          VehicleTO result = new VehicleTO();
          result.setName(vehicle.getName())
              .setProperties(convertProperties(vehicle.getProperties()));
          result.setLength(vehicle.getLength())
              .setEnergyLevelCritical(vehicle.getEnergyLevelCritical())
              .setEnergyLevelGood(vehicle.getEnergyLevelGood())
              .setEnergyLevelFullyRecharged(vehicle.getEnergyLevelFullyRecharged())
              .setEnergyLevelSufficientlyRecharged(vehicle.getEnergyLevelSufficientlyRecharged())
              .setMaxVelocity(vehicle.getMaxVelocity())
              .setMaxReverseVelocity(vehicle.getMaxReverseVelocity());
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<LocationTypeTO> convertLocationTypes(V002PlantModelTO to) {
    return to.getLocationTypes().stream()
        .map(locationType -> {
          LocationTypeTO result = new LocationTypeTO();
          result.setName(locationType.getName())
              .setProperties(convertProperties(locationType.getProperties()));
          result.setLocationNamePrefix(locationType.getLocationNamePrefix())
              .setAllowedOperations(convertAllowedOperations(locationType.getAllowedOperations()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<AllowedOperationTO> convertAllowedOperations(
      List<org.opentcs.util.persistence.v002.AllowedOperationTO> tos) {
    return tos.stream()
        .map(allowedOperation -> {
          AllowedOperationTO result = new AllowedOperationTO();
          result.setName(allowedOperation.getName());
          result.setProperties(convertProperties(allowedOperation.getProperties()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<LocationTO> convertLocations(V002PlantModelTO to) {
    return to.getLocations().stream()
        .map(location -> {
          LocationTO result = new LocationTO();
          result.setName(location.getName())
              .setProperties(convertProperties(location.getProperties()));
          result.setxPosition(location.getxPosition())
              .setyPosition(location.getyPosition())
              .setzPosition(location.getzPosition())
              .setType(location.getType())
              .setLinks(convertLinks(location))
              .setLocked(location.isLocked());
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<LocationTO.Link> convertLinks(org.opentcs.util.persistence.v002.LocationTO to) {
    return to.getLinks().stream()
        .map(link -> {
          return new LocationTO.Link()
              .setPoint(link.getPoint())
              .setAllowedOperations(convertAllowedOperations(link.getAllowedOperations()));
        })
        .collect(Collectors.toList());
  }

  private List<BlockTO> convertBlocks(V002PlantModelTO to) {
    return to.getBlocks().stream()
        .map(block -> {
          BlockTO result = new BlockTO();
          result.setName(block.getName())
              .setProperties(convertProperties(block.getProperties()));
          result.setType(block.getType())
              .setMembers(convertMembers(block.getMembers()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<MemberTO> convertMembers(List<org.opentcs.util.persistence.v002.MemberTO> tos) {
    return tos.stream()
        .map(member -> {
          MemberTO result = new MemberTO();
          result.setName(member.getName())
              .setProperties(convertProperties(member.getProperties()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<GroupTO> convertGroups(V002PlantModelTO to) {
    return to.getGroups().stream()
        .map(group -> {
          GroupTO result = new GroupTO();
          result.setName(group.getName())
              .setProperties(convertProperties(group.getProperties()));
          result.setMembers(convertMembers(group.getMembers()));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<VisualLayoutTO> convertVisualLayouts(V002PlantModelTO to) {
    return to.getVisualLayouts().stream()
        .map(visualLayout -> {
          VisualLayoutTO result = new VisualLayoutTO();
          result.setName(visualLayout.getName())
              .setProperties(convertProperties(visualLayout.getProperties()));
          result.setScaleX(visualLayout.getScaleX())
              .setScaleY(visualLayout.getScaleY())
              .setShapeLayoutElements(convertShapeLayoutElements(visualLayout))
              .setModelLayoutElements(convertModelLayoutElements(visualLayout));
          return result;
        })
        .collect(Collectors.toList());
  }

  private List<VisualLayoutTO.ShapeLayoutElement> convertShapeLayoutElements(
      org.opentcs.util.persistence.v002.VisualLayoutTO to) {
    return to.getShapeLayoutElements().stream()
        .map(shapeLayoutElement -> {
          return new VisualLayoutTO.ShapeLayoutElement()
              .setLayer(shapeLayoutElement.getLayer())
              .setProperties(convertProperties(shapeLayoutElement.getProperties()));
        })
        .collect(Collectors.toList());
  }

  private List<VisualLayoutTO.ModelLayoutElement> convertModelLayoutElements(
      org.opentcs.util.persistence.v002.VisualLayoutTO to) {
    return to.getModelLayoutElements().stream()
        .map(modelLayoutElement -> {
          return new VisualLayoutTO.ModelLayoutElement()
              .setVisualizedObjectName(modelLayoutElement.getVisualizedObjectName())
              .setLayer(modelLayoutElement.getLayer())
              .setProperties(convertProperties(modelLayoutElement.getProperties()));
        })
        .collect(Collectors.toList());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/order/TransportOrderHistoryCodes.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.order;

/**
 * Defines constants for basic history event codes related to transport orders and documents how the
 * respective supplementary information is to be interpreted.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface TransportOrderHistoryCodes {

  /**
   * An event code indicating a transport order has been created.
   * <p>
   * The history entry's supplement is empty.
   * </p>
   */
  String ORDER_CREATED = "tcsHistory:orderCreated";
  /**
   * An event code indicating dispatching of a transport order to a vehicle has been deferred.
   * <p>
   * The history entry's supplement contains a list of reasons for the deferral.
   * </p>
   */
  String ORDER_DISPATCHING_DEFERRED = "tcsHistory:orderDispatchingDeferred";
  /**
   * An event code indicating dispatching of a transport order to a vehicle has been resumed.
   * <p>
   * The history entry's supplement is empty.
   * </p>
   */
  String ORDER_DISPATCHING_RESUMED = "tcsHistory:orderDispatchingResumed";
  /**
   * An event code indicating a transport order was assigned to a vehicle.
   * <p>
   * The history entry's supplement contains the name of the vehicle the transport order was
   * assigned to.
   * </p>
   */
  String ORDER_ASSIGNED_TO_VEHICLE = "tcsHistory:orderAssignedToVehicle";
  /**
   * An event code indicating a transport order was reserved for a vehicle.
   * <p>
   * The history entry's supplement contains the name of the vehicle the transport order was
   * reserved for.
   * </p>
   */
  String ORDER_RESERVED_FOR_VEHICLE = "tcsHistory:orderReservedForVehicle";
  /**
   * An event code indicating a transport order's processing vehicle changed.
   * <p>
   * The history entry's supplement contains the name of the new processing vehicle, or the empty
   * string, if the processing vehicle was unset.
   * </p>
   */
  String ORDER_PROCESSING_VEHICLE_CHANGED = "tcsHistory:orderProcVehicleChanged";
  /**
   * An event code indicating a transport order was marked as being in a final state.
   * <p>
   * The history entry's supplement is empty.
   * </p>
   */
  String ORDER_REACHED_FINAL_STATE = "tcsHistory:orderReachedFinalState";
  /**
   * An event code indicating one of a transport order's drive orders has been finished.
   * <p>
   * The history entry's supplement is empty.
   * </p>
   */
  String ORDER_DRIVE_ORDER_FINISHED = "tcsHistory:orderFinishedDriveOrder";
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/ComplexPropertyCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTable;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.dialogs.StandardDetailsDialog;
import org.opentcs.guing.components.properties.type.AbstractComplexProperty;

/**
 * A cell editor for a complex property.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class ComplexPropertyCellEditor
    extends javax.swing.AbstractCellEditor
    implements javax.swing.table.TableCellEditor {

  /**
   * The button for showing the details dialog.
   */
  private final JButton fButton = new JButton();
  /**
   * Provides the appropriate dialog content for a given property.
   */
  private final Map<Class<? extends AbstractComplexProperty>, Provider<DetailsDialogContent>> contentMap;
  /**
   * A parent for dialogs created by this instance.
   */
  private final JPanel dialogParent;
  /**
   * The property being edited.
   */
  private AbstractComplexProperty fProperty;

  /**
   * Creates a new instance.
   *
   * @param contentMap Provides the appropriate content for a given property.
   * @param dialogParent A parent for dialogs created by this instance.
   */
  @Inject
  public ComplexPropertyCellEditor(
      Map<Class<? extends AbstractComplexProperty>, Provider<DetailsDialogContent>> contentMap,
      @Assisted JPanel dialogParent) {
    this.contentMap = requireNonNull(contentMap, "contentMap");
    this.dialogParent = requireNonNull(dialogParent, "dialogParent");

    fButton.setFont(new Font("Dialog", Font.PLAIN, 12));
    fButton.setBorder(null);
    fButton.setHorizontalAlignment(JButton.LEFT);
    fButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        showDialog();
      }
    });
  }

  @Override
  public Object getCellEditorValue() {
    return fProperty;
  }

  @Override
  public Component getTableCellEditorComponent(
      JTable table, Object value, boolean isSelected, int row, int column) {

    fProperty = (AbstractComplexProperty) value;
    fButton.setText(fProperty.toString());
    fButton.setBackground(table.getBackground());

    return fButton;
  }

  /**
   * Shows the dialog for editing the property.
   */
  private void showDialog() {
    DetailsDialogContent content = contentMap.get(fProperty.getClass()).get();

    StandardDetailsDialog detailsDialog
        = new StandardDetailsDialog(dialogParent, true, content);
    detailsDialog.setLocationRelativeTo(dialogParent);

    detailsDialog.getDialogContent().setProperty(fProperty);
    detailsDialog.activate();
    detailsDialog.setVisible(true);

    if (detailsDialog.getReturnStatus() == StandardDetailsDialog.RET_OK) {
      stopCellEditing();
    }
    else {
      cancelCellEditing();
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/Scheduler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.TCSResource;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * Manages resources used by clients (vehicles) to help prevent both collisions and deadlocks.
 * <p>
 * Every client usually interacts with the <code>Scheduler</code> according to the following
 * workflow:
 * </p>
 * <ol>
 * <li>
 * Initially, the client calls
 * {@link #allocateNow(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocateNow()}
 * when a vehicle pops up somewhere in the driving course.
 * This usually happens either upon kernel startup or when a vehicle communicates its current
 * position to the kernel for the first time.
 * </li>
 * <li>
 * Once a transport order is assigned to a vehicle, the client calls
 * {@link #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List) claim()} with the
 * complete sequence of resource sets the vehicle needs to process the transport order - usually
 * each containing a point and the path leading to it.
 * </li>
 * <li>
 * As the vehicle processes the transport order, the client subsequently calls
 * {@link #allocate(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocate()} for
 * resources needed next (for reaching the next point on the route).
 * The <code>Scheduler</code> asynchronously calls back either
 * {@link Client#allocationSuccessful(java.util.Set)} or
 * {@link Client#allocationFailed(java.util.Set)}, informing the client about the result.
 * Upon allocating the resources for the client, it also implicitly removes them from the head of
 * the client's claim sequence.
 * </li>
 * <li>
 * As the vehicle passes points (and paths) on the route, the client calls
 * {@link #free(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) free()} for resources
 * it does not need any more, allowing these resources to be allocated by other clients.
 * </li>
 * </ol>
 * <p>
 * At the end of this process, the client's claim sequence is empty, and only the most recently
 * allocated resources are still assigned to it, reflecting the vehicle's current position.
 * (If the vehicle has disappeared from the driving course after processing the transport order, the
 * client would call {@link #freeAll(org.opentcs.components.kernel.Scheduler.Client) freeAll()} to
 * inform the <code>Scheduler</code> about this.)
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface Scheduler
    extends Lifecycle {

  /**
   * The key of a path property defining the direction in which a vehicle is entering a block when
   * it's taking the path.
   */
  String PROPKEY_BLOCK_ENTRY_DIRECTION = "tcs:blockEntryDirection";

  /**
   * Sets/Updates the resource claim for a vehicle.
   * <p>
   * <em>Claimed</em> resources are resources that a vehicle will eventually require for executing
   * its movements in the future, but for which it does not request allocation, yet.
   * Claiming resources provides information to the scheduler about future allocations <em>and their
   * intended order</em>, allowing the scheduler to consider these information for its resource
   * planning.
   * </p>
   * <p>
   * Resources can be claimed by multiple vehicles at the same time.
   * This is different from allocations:
   * Only a single vehicle can allocate a resource at the same time.
   * </p>
   *
   * @param client The client claiming the resources.
   * @param resourceSequence The sequence of resources claimed. May be empty to clear the client's
   * claim.
   */
  void claim(@Nonnull Client client, @Nonnull List<Set<TCSResource<?>>> resourceSequence);

  /**
   * Notifies the scheduler that the given client has now reached the given index in its claimed
   * resource sequence, and that the client does not need the resources preceding the index in the
   * sequence, any more.
   *
   * @param client The client.
   * @param index The new index in the client's claimed resource sequence.
   * @throws IllegalArgumentException If the client does not hold a claim, or if the new index is
   * larger than a valid index in its claim's resource sequence, or if the new index is not larger
   * than the current index.
   * @deprecated Stick to
   * {@link #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List) claim()} and
   * {@link #allocate(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocate()}.
   * They implicitly update both the set of claimed and the set of allocated resources.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void updateProgressIndex(@Nonnull Client client, int index)
      throws IllegalArgumentException {
  }

  /**
   * Unclaims a set of resources claimed by a vehicle.
   *
   * @param client The client unclaiming the resources.
   * @throws IllegalArgumentException If the given client does not hold a claim.
   * @deprecated Use {@link #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List)}
   * with an empty list, instead.
   */
  @Deprecated
  @ScheduledApiChange(when = "6.0", details = "Will be removed.")
  default void unclaim(@Nonnull Client client)
      throws IllegalArgumentException {
    claim(client, List.of());
  }

  /**
   * Requests allocation of the given resources.
   * The client will be informed via a callback to
   * {@link Client#allocationSuccessful(java.util.Set)} or
   * {@link Client#allocationFailed(java.util.Set)} whether the allocation was successful or not.
   * <ul>
   * <li>
   * Clients may only allocate resources in the order they have previously
   * {@link #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List) claim()}ed them.
   * </li>
   * <li>
   * Upon allocation, the scheduler will implicitly remove the set of allocated resources from (the
   * head of) the client's claim sequence.
   * </li>
   * <li>
   * As a result, a client may only allocate the set of resources at the head of its claim sequence.
   * </li>
   * </ul>
   *
   * @param client The client requesting the resources.
   * @param resources The resources to be allocated.
   * @throws IllegalArgumentException If the set of resources to be allocated is not equal to the
   * <em>next</em> set in the sequence of currently claimed resources, or if the client has already
   * requested resources that have not yet been granted.
   * @see #claim(org.opentcs.components.kernel.Scheduler.Client, java.util.List)
   */
  void allocate(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources)
      throws IllegalArgumentException;

  /**
   * Informs the scheduler that a set of resources are to be allocated for the given client
   * <em>immediately</em>.
   * <p>
   * Note the following:
   * </p>
   * <ul>
   * <li>
   * This method should only be called in urgent/emergency cases, for instance if a vehicle has been
   * moved to a different point manually, which has to be reflected by resource allocation in the
   * scheduler.
   * </li>
   * <li>
   * Unlike
   * {@link #allocate(org.opentcs.components.kernel.Scheduler.Client, java.util.Set) allocate()},
   * this method does not block, i.e. the operation happens synchronously.
   * </li>
   * <li>
   * This method does <em>not</em> implicitly deallocate or unclaim any other resources for the
   * client.
   * </li>
   * </ul>
   *
   * @param client The client requesting the resources.
   * @param resources The resources requested.
   * @throws ResourceAllocationException If it's impossible to allocate the given set of resources
   * for the given client.
   */
  void allocateNow(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources)
      throws ResourceAllocationException;

  /**
   * Releases a set of resources allocated by a client.
   *
   * @param client The client releasing the resources.
   * @param resources The resources released. Any resources in the given set not allocated by the
   * given client are ignored.
   */
  void free(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources);

  /**
   * Releases all resources allocated by the given client.
   *
   * @param client The client.
   */
  void freeAll(@Nonnull Client client);

  /**
   * Releases all pending resource allocations for the given client.
   *
   * @param client The client.
   */
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default void clearPendingAllocations(@Nonnull Client client) {
  }

  /**
   * Explicitly triggers a rescheduling run during which the scheduler tries to allocate resources
   * for all waiting clients.
   */
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default void reschedule() {
  }

  /**
   * Returns all resource allocations as a map of client IDs to resources.
   *
   * @return All resource allocations as a map of client IDs to resources.
   */
  @Nonnull
  Map<String, Set<TCSResource<?>>> getAllocations();

  /**
   * Informs the scheduler that a set of resources was successfully prepared in order of allocating
   * them to a client.
   *
   * @param module The module a preparation was necessary for.
   * @param client The client that requested the preparation/allocation.
   * @param resources The resources that are now prepared for the client.
   */
  void preparationSuccessful(@Nonnull Module module,
                             @Nonnull Client client,
                             @Nonnull Set<TCSResource<?>> resources);

  /**
   * Defines callback methods for clients of the resource scheduler.
   */
  interface Client {

    /**
     * Returns an ID string for this client.
     * The returned string should be unique among all clients in the system.
     *
     * @return An unique ID string for this client.
     */
    @Nonnull
    String getId();

    /**
     * Called when resources have been reserved for this client.
     *
     * @param resources The resources reserved.
     * @return <code>true</code> if, and only if, this client accepts the resources allocated. A
     * return value of <code>false</code> indicates this client does not need the given resources
     * (any more), freeing them implicitly, but not restoring any previous claim.
     */
    boolean allocationSuccessful(@Nonnull Set<TCSResource<?>> resources);

    /**
     * Called if it was impossible to allocate a requested set of resources for this client.
     *
     * @param resources The resources which could not be reserved.
     */
    void allocationFailed(@Nonnull Set<TCSResource<?>> resources);
  }

  /**
   * A scheduler module.
   */
  interface Module
      extends Lifecycle {

    /**
     * Sets a client's <i>total claim</i>.
     * With vehicles, this is equivalent to the route a vehicle plans to take.
     *
     * @param client The client the resource sequence is claimed by.
     * @param claim The resource sequence, i.e. total claim.
     * @deprecated Redundant - use
     * {@link #setAllocationState(org.opentcs.components.kernel.Scheduler.Client, java.util.Set, java.util.List)}
     * instead/exclusively.
     */
    @Deprecated
    @ScheduledApiChange(when = "6.0", details = "Will be removed.")
    default void claim(@Nonnull Client client, @Nonnull List<Set<TCSResource<?>>> claim) {
    }

    /**
     * Resets a client's <i>total claim</i>.
     *
     * @param client The client for which to reset the claim.
     * @deprecated Redundant - use
     * {@link #setAllocationState(org.opentcs.components.kernel.Scheduler.Client, java.util.Set, java.util.List)}
     * instead/exclusively.
     */
    @Deprecated
    @ScheduledApiChange(when = "6.0", details = "Will be removed.")
    default void unclaim(@Nonnull Client client) {
    }

    /**
     * Informs this module about a client's current allocation state.
     *
     * @param client The client.
     * @param alloc The client's currently allocated resources.
     * @param remainingClaim The client's remaining claim.
     */
    void setAllocationState(@Nonnull Client client,
                            @Nonnull Set<TCSResource<?>> alloc,
                            @Nonnull List<Set<TCSResource<?>>> remainingClaim);

    /**
     * Checks if the resulting system state is safe if the given set of resources
     * would be allocated by the given resource user.
     *
     * @param client The <code>ResourceUser</code> requesting resources set.
     * @param resources The requested resources.
     * @return <code>true</code> if this module thinks the given resources may be allocated for the
     * given client.
     */
    boolean mayAllocate(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources);

    /**
     * Lets this module prepare the given resources so they can be allocated to a client.
     *
     * @param client The client the resources are being prepared for.
     * @param resources The resources to be prepared.
     */
    void prepareAllocation(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources);

    /**
     * Checks if this module is done preparing the given resources for a client.
     *
     * @param client The client the resources are being prepared for.
     * @param resources The resources to be checked.
     * @return <code>true</code> if the resoruces are prepared for a client.
     */
    boolean hasPreparedAllocation(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources);

    /**
     * Informs this module about resources being fully released by a client.
     *
     * @param client The client releasing the resources.
     * @param resources The resources being released.
     */
    void allocationReleased(@Nonnull Client client, @Nonnull Set<TCSResource<?>> resources);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/order/TransportOrder.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.order;

import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_CREATED;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_DRIVE_ORDER_FINISHED;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_PROCESSING_VEHICLE_CHANGED;
import static org.opentcs.data.order.TransportOrderHistoryCodes.ORDER_REACHED_FINAL_STATE;

/**
 * Represents a sequence of movements and operations that are to be executed by a {@link Vehicle}.
 * <p>
 * A TransportOrder basically encapsulates a list of {@link DriveOrder} instances.
 * </p>
 * <p>
 * Transport orders may depend on other transport orders in the systems, which means they may not be
 * processed before the orders they depend on have been processed.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrder
    extends TCSObject<TransportOrder>
    implements Serializable {

  /**
   * The type of this transport order.
   */
  @Nonnull
  private final String type;
  /**
   * A set of TransportOrders that must have been finished before this one may
   * be processed.
   */
  @Nonnull
  private final Set<TCSObjectReference<TransportOrder>> dependencies;
  /**
   * The drive orders this transport order consists of.
   */
  @Nonnull
  private final List<DriveOrder> driveOrders;
  /**
   * An optional token for reserving peripheral devices while processing this transport order.
   */
  @Nullable
  private final String peripheralReservationToken;
  /**
   * The index of the currently processed drive order.
   */
  private final int currentDriveOrderIndex;
  /**
   * This transport order's current state.
   */
  @Nonnull
  private final State state;
  /**
   * The point of time at which this transport order was created.
   */
  private final Instant creationTime;
  /**
   * The point of time at which processing of this transport order must be finished.
   */
  private final Instant deadline;
  /**
   * The point of time at which processing of this transport order was finished.
   */
  private final Instant finishedTime;
  /**
   * A reference to the vehicle that is intended to process this transport
   * order. If this order is free to be processed by any vehicle, this is
   * <code>null</code>.
   */
  @Nullable
  private final TCSObjectReference<Vehicle> intendedVehicle;
  /**
   * A reference to the vehicle currently processing this transport order. If
   * this transport order is not being processed at the moment, this is
   * <code>null</code>.
   */
  @Nullable
  private final TCSObjectReference<Vehicle> processingVehicle;
  /**
   * The order sequence this transport order belongs to. May be
   * <code>null</code> in case this order isn't part of any sequence.
   */
  @Nullable
  private final TCSObjectReference<OrderSequence> wrappingSequence;
  /**
   * Whether this order is dispensable (may be withdrawn automatically).
   */
  private final boolean dispensable;

  /**
   * Creates a new TransportOrder.
   *
   * @param name This transport order's name.
   * @param driveOrders A list of drive orders to be processed when processing this transport
   * order.
   */
  public TransportOrder(String name, List<DriveOrder> driveOrders) {
    super(name,
          new HashMap<>(),
          new ObjectHistory().withEntryAppended(new ObjectHistory.Entry(ORDER_CREATED)));
    this.type = OrderConstants.TYPE_NONE;
    this.driveOrders = requireNonNull(driveOrders, "driveOrders");
    this.peripheralReservationToken = null;
    this.currentDriveOrderIndex = -1;
    this.state = State.RAW;
    this.creationTime = Instant.EPOCH;
    this.intendedVehicle = null;
    this.processingVehicle = null;
    this.deadline = Instant.MAX;
    this.finishedTime = Instant.MAX;
    this.dispensable = false;
    this.wrappingSequence = null;
    this.dependencies = new LinkedHashSet<>();
  }

  /**
   * Creates a new TransportOrder.
   *
   * @param objectID This transport order's ID.
   * @param name This transport order's name.
   * @param destinations A list of destinations that are to be travelled to
   * when processing this transport order.
   * @param creationTime The creation time stamp to be set.
   */
  private TransportOrder(String name,
                         Map<String, String> properties,
                         ObjectHistory history,
                         String type,
                         List<DriveOrder> driveOrders,
                         String peripheralReservationToken,
                         int currentDriveOrderIndex,
                         Instant creationTime,
                         TCSObjectReference<Vehicle> intendedVehicle,
                         Instant deadline,
                         boolean dispensable,
                         TCSObjectReference<OrderSequence> wrappingSequence,
                         Set<TCSObjectReference<TransportOrder>> dependencies,
                         TCSObjectReference<Vehicle> processingVehicle,
                         State state,
                         Instant finishedTime) {
    super(name, properties, history);
    this.type = requireNonNull(type, "type");
    requireNonNull(driveOrders, "driveOrders");
    this.driveOrders = new LinkedList<>();
    for (DriveOrder driveOrder : driveOrders) {
      this.driveOrders.add(driveOrder.withTransportOrder(this.getReference()));
    }

    this.peripheralReservationToken = peripheralReservationToken;
    this.currentDriveOrderIndex = currentDriveOrderIndex;
    this.creationTime = requireNonNull(creationTime, "creationTime");
    this.intendedVehicle = intendedVehicle;
    this.deadline = requireNonNull(deadline, "deadline");
    this.dispensable = dispensable;
    this.wrappingSequence = wrappingSequence;
    this.dependencies = requireNonNull(dependencies, "dependencies");
    this.processingVehicle = processingVehicle;
    this.state = requireNonNull(state, "state");
    this.finishedTime = requireNonNull(finishedTime, "finishedTime");
  }

  @Override
  public TransportOrder withProperty(String key, String value) {
    return new TransportOrder(getName(),
                              propertiesWith(key, value),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  @Override
  public TransportOrder withProperties(Map<String, String> properties) {
    return new TransportOrder(getName(),
                              properties,
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  @Override
  public TransportOrder withHistoryEntry(ObjectHistory.Entry entry) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory().withEntryAppended(entry),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  @Override
  public TransportOrder withHistory(ObjectHistory history) {
    return new TransportOrder(getName(),
                              getProperties(),
                              history,
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Retruns this transport order's type.
   *
   * @return This transport order's type.
   */
  public String getType() {
    return type;
  }

  /**
   * Creates a copy of this obejct, with the given type.
   *
   * @param type The tpye to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withType(String type) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns this transport order's current state.
   *
   * @return This transport order's current state.
   */
  public State getState() {
    return state;
  }

  /**
   * Checks if this transport order's current state is equal to the given one.
   *
   * @param otherState The state to compare to this transport order's one.
   * @return <code>true</code> if, and only if, the given state is equal to this
   * transport order's one.
   */
  public boolean hasState(State otherState) {
    requireNonNull(otherState, "otherState");
    return this.state.equals(otherState);
  }

  /**
   * Creates a copy of this object, with the given state.
   *
   * @param state The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withState(@Nonnull State state) {
    // XXX Finished time should probably not be set implicitly.
    return new TransportOrder(getName(),
                              getProperties(),
                              historyForNewState(state),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              state == State.FINISHED ? Instant.now() : finishedTime);
  }

  /**
   * Returns this transport order's creation time.
   *
   * @return This transport order's creation time.
   */
  public Instant getCreationTime() {
    return creationTime;
  }

  /**
   * Creates a copy of this object, with the given creation time.
   *
   * @param creationTime The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withCreationTime(Instant creationTime) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns this transport order's deadline. If the value of transport order's
   * deadline was not changed, the initial value {@link Instant#MAX} is returned.
   *
   * @return This transport order's deadline or the initial deadline value.{@link Instant#MAX}, if
   * the deadline was not changed.
   */
  public Instant getDeadline() {
    return deadline;
  }

  /**
   * Creates a copy of this object, with the given deadline.
   *
   * @param deadline The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withDeadline(Instant deadline) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns the point of time at which this transport order was finished.
   * If the transport order has not been finished, yet, {@link Instant#MAX} is returned.
   *
   * @return The point of time at which this transport order was finished, or {@link Instant#MAX},
   * if the transport order has not been finished, yet.
   */
  public Instant getFinishedTime() {
    return finishedTime;
  }

  /**
   * Creates a copy of this object, with the given finished time.
   *
   * @param finishedTime The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withFinishedTime(Instant finishedTime) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns a reference to the vehicle that is intended to process this
   * transport order.
   *
   * @return A reference to the vehicle that is intended to process this
   * transport order. If this order is free to be processed by any vehicle,
   * <code>null</code> is returned.
   */
  @Nullable
  public TCSObjectReference<Vehicle> getIntendedVehicle() {
    return intendedVehicle;
  }

  /**
   * Creates a copy of this object, with the given intended vehicle.
   *
   * @param intendedVehicle The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withIntendedVehicle(@Nullable TCSObjectReference<Vehicle> intendedVehicle) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns a reference to the vehicle currently processing this transport
   * order.
   *
   * @return A reference to the vehicle currently processing this transport
   * order. If this transport order is not currently being processed,
   * <code>null</code> is returned.
   */
  @Nullable
  public TCSObjectReference<Vehicle> getProcessingVehicle() {
    return processingVehicle;
  }

  /**
   * Creates a copy of this object, with the given processing vehicle.
   *
   * @param processingVehicle The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withProcessingVehicle(
      @Nullable TCSObjectReference<Vehicle> processingVehicle) {
    return new TransportOrder(getName(),
                              getProperties(),
                              historyForNewProcessingVehicle(processingVehicle),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns the set of transport orders this order depends on.
   *
   * @return The set of transport orders this order depends on.
   */
  public Set<TCSObjectReference<TransportOrder>> getDependencies() {
    return dependencies;
  }

  /**
   * Creates a copy of this object, with the given dependencies.
   *
   * @param dependencies The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withDependencies(
      @Nonnull Set<TCSObjectReference<TransportOrder>> dependencies) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns a list of DriveOrders that have been processed already.
   *
   * @return A list of DriveOrders that have been processed already.
   */
  @Nonnull
  public List<DriveOrder> getPastDriveOrders() {
    List<DriveOrder> result = new ArrayList<>();
    for (int i = 0; i < currentDriveOrderIndex; i++) {
      result.add(driveOrders.get(i));
    }
    return result;
  }

  /**
   * Returns a list of DriveOrders that still need to be processed.
   *
   * @return A list of DriveOrders that still need to be processed.
   */
  @Nonnull
  public List<DriveOrder> getFutureDriveOrders() {
    List<DriveOrder> result = new ArrayList<>();
    for (int i = currentDriveOrderIndex + 1; i < driveOrders.size(); i++) {
      result.add(driveOrders.get(i));
    }
    return result;
  }

  /**
   * Creates a copy of this object, with the given drive orders.
   *
   * @param driveOrders The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withDriveOrders(@Nonnull List<DriveOrder> driveOrders) {
    requireNonNull(driveOrders, "driveOrders");
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns the current drive order, or <code>null</code>, if no drive order is
   * currently being processed.
   *
   * @return the current drive order, or <code>null</code>, if no drive order is
   * currently being processed.
   */
  @Nullable
  public DriveOrder getCurrentDriveOrder() {
    return (currentDriveOrderIndex >= 0 && currentDriveOrderIndex < driveOrders.size())
        ? driveOrders.get(currentDriveOrderIndex)
        : null;
  }

  /**
   * Returns a list of all drive orders, i.e. the past, current and future drive
   * orders.
   *
   * @return A list of all drive orders, i.e. the past, current and future drive
   * orders. If no drive orders exist, the returned list is empty.
   */
  @Nonnull
  public List<DriveOrder> getAllDriveOrders() {
    return new ArrayList<>(driveOrders);
  }

  /**
   * Returns an optional token for reserving peripheral devices while processing this transport
   * order.
   *
   * @return An optional token for reserving peripheral devices while processing this transport
   * order.
   */
  @Nullable
  public String getPeripheralReservationToken() {
    return peripheralReservationToken;
  }

  /**
   * Creates a copy of this object, with the given reservation token.
   *
   * @param peripheralReservationToken The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withPeripheralReservationToken(
      @Nullable String peripheralReservationToken) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns the index of the currently processed drive order.
   *
   * @return The index of the currently processed drive order.
   */
  public int getCurrentDriveOrderIndex() {
    return currentDriveOrderIndex;
  }

  /**
   * Creates a copy of this object, with the given drive order index.
   *
   * @param currentDriveOrderIndex The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withCurrentDriveOrderIndex(int currentDriveOrderIndex) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Creates a copy of this object, with the given current drive order state.
   *
   * @param driveOrderState The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withCurrentDriveOrderState(@Nonnull DriveOrder.State driveOrderState) {
    requireNonNull(driveOrderState, "driveOrderState");

    List<DriveOrder> newDriveOrders = new ArrayList<>(this.driveOrders);
    newDriveOrders.set(currentDriveOrderIndex,
                       newDriveOrders.get(currentDriveOrderIndex).withState(driveOrderState));

    return new TransportOrder(getName(),
                              getProperties(),
                              historyForNewDriveOrderState(driveOrderState),
                              type,
                              newDriveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Returns the order sequence this order belongs to, or <code>null</code>, if
   * it doesn't belong to any sequence.
   *
   * @return The order sequence this order belongs to, or <code>null</code>, if
   * it doesn't belong to any sequence.
   */
  @Nullable
  public TCSObjectReference<OrderSequence> getWrappingSequence() {
    return wrappingSequence;
  }

  /**
   * Creates a copy of this object, with the given wrapping sequence.
   *
   * @param wrappingSequence The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withWrappingSequence(
      @Nullable TCSObjectReference<OrderSequence> wrappingSequence) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  /**
   * Checks if this order is dispensable.
   *
   * @return <code>true</code> if, and only if, this order is dispensable.
   */
  public boolean isDispensable() {
    return dispensable;
  }

  /**
   * Creates a copy of this object, with the given dispensable flag.
   *
   * @param dispensable The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public TransportOrder withDispensable(boolean dispensable) {
    return new TransportOrder(getName(),
                              getProperties(),
                              getHistory(),
                              type,
                              driveOrders,
                              peripheralReservationToken,
                              currentDriveOrderIndex,
                              creationTime,
                              intendedVehicle,
                              deadline,
                              dispensable,
                              wrappingSequence,
                              dependencies,
                              processingVehicle,
                              state,
                              finishedTime);
  }

  @Override
  public String toString() {
    return "TransportOrder{"
        + "name=" + getName()
        + ", state=" + state
        + ", intendedVehicle=" + intendedVehicle
        + ", processingVehicle=" + processingVehicle
        + ", creationTime=" + creationTime
        + ", deadline=" + deadline
        + ", finishedTime=" + finishedTime
        + ", wrappingSequence=" + wrappingSequence
        + ", dispensable=" + dispensable
        + ", type=" + type
        + ", peripheralReservationToken=" + peripheralReservationToken
        + ", dependencies=" + dependencies
        + ", driveOrders=" + driveOrders
        + ", currentDriveOrderIndex=" + currentDriveOrderIndex
        + '}';
  }

  private ObjectHistory historyForNewState(State state) {
    return state.isFinalState()
        ? getHistory().withEntryAppended(new ObjectHistory.Entry(ORDER_REACHED_FINAL_STATE))
        : getHistory();
  }

  private ObjectHistory historyForNewDriveOrderState(DriveOrder.State state) {
    return state == DriveOrder.State.FINISHED
        ? getHistory().withEntryAppended(new ObjectHistory.Entry(ORDER_DRIVE_ORDER_FINISHED))
        : getHistory();
  }

  private ObjectHistory historyForNewProcessingVehicle(TCSObjectReference<Vehicle> ref) {
    return getHistory().withEntryAppended(
        new ObjectHistory.Entry(ORDER_PROCESSING_VEHICLE_CHANGED,
                                ref == null ? "" : ref.getName())
    );
  }

  /**
   * This enumeration defines the various states a transport order may be in.
   */
  public static enum State {

    /**
     * A transport order's initial state.
     * A transport order remains in this state until its parameters have been
     * set up completely.
     */
    RAW,
    /**
     * Set (by a user/client) when a transport order's parameters have been set
     * up completely and the kernel should dispatch it when possible.
     */
    ACTIVE,
    /**
     * Marks a transport order as ready to be dispatched to a vehicle (i.e. all
     * its dependencies have been finished).
     */
    DISPATCHABLE,
    /**
     * Marks a transport order as being processed by a vehicle.
     */
    BEING_PROCESSED,
    /**
     * Indicates the transport order is withdrawn from a processing vehicle but
     * not yet in its final state (which will be FAILED), as the vehicle has not
     * yet finished/cleaned up.
     */
    WITHDRAWN,
    /**
     * Marks a transport order as successfully completed.
     */
    FINISHED,
    /**
     * General failure state that marks a transport order as failed.
     */
    FAILED,
    /**
     * Failure state that marks a transport order as unroutable, i.e. it is
     * impossible to find a route that would allow a vehicle to process the
     * transport order completely.
     */
    UNROUTABLE;

    /**
     * Checks if this state is a final state for a transport order.
     *
     * @return <code>true</code> if, and only if, this state is a final state
     * for a transport order - i.e. FINISHED, FAILED or UNROUTABLE.
     */
    public boolean isFinalState() {
      return this.equals(FINISHED)
          || this.equals(FAILED)
          || this.equals(UNROUTABLE);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/event/OperationModeChangeEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.event;

import java.util.EventObject;
import static java.util.Objects.requireNonNull;
import org.opentcs.guing.application.OperationMode;

/**
 * Informs listeners about a change of the application's mode of operation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OperationModeChangeEvent
    extends EventObject {

  /**
   * The old operation mode.
   */
  private final OperationMode oldMode;
  /**
   * The new/current operation mode.
   */
  private final OperationMode newMode;

  /**
   * Creates a new instance.
   *
   * @param source The source of this event.
   * @param oldMode The old operation mode.
   * @param newMode The new/current operation mode.
   */
  public OperationModeChangeEvent(Object source,
                                  OperationMode oldMode,
                                  OperationMode newMode) {
    super(source);
    this.oldMode = requireNonNull(oldMode, "oldMode");
    this.newMode = requireNonNull(newMode, "newMode");
  }

  /**
   * Returns the old operation mode.
   *
   * @return The old operation mode.
   */
  public OperationMode getOldMode() {
    return oldMode;
  }

  /**
   * Returns the new/current operation mode.
   *
   * @return The new/current operation mode.
   */
  public OperationMode getNewMode() {
    return newMode;
  }

  @Override
  public String toString() {
    return "OperationModeChangeEvent{"
        + "oldMode=" + oldMode
        + ", newMode=" + newMode
        + ", source=" + getSource()
        + '}';
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/adminwebapi/v1/Status.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.adminwebapi.v1;

/**
 * Describes the kernel process's current status.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Status {

  private String heapSize = String.valueOf(Runtime.getRuntime().totalMemory());

  private String maxHeapSize = String.valueOf(Runtime.getRuntime().maxMemory());

  private String freeInHeap = String.valueOf(Runtime.getRuntime().freeMemory());

  public Status() {
  }

  public String getHeapSize() {
    return heapSize;
  }

  public void setHeapSize(String heapSize) {
    this.heapSize = heapSize;
  }

  public String getMaxHeapSize() {
    return maxHeapSize;
  }

  public void setMaxHeapSize(String maxHeapSize) {
    this.maxHeapSize = maxHeapSize;
  }

  public String getFreeInHeap() {
    return freeInHeap;
  }

  public void setFreeInHeap(String freeInHeap) {
    this.freeInHeap = freeInHeap;
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/LinkActionsEditorPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JDialog;
import org.opentcs.guing.components.dialogs.StandardDetailsDialog;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Allows editing of actions that a vehicle can execute at a station.
 * Which actions are possible is determined by the station type.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class LinkActionsEditorPanel
    extends StringSetPropertyEditorPanel {

  /**
   * The bundle to be used.
   */
  private final ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverview.PROPERTIES_PATH);

  /**
   * Creates a new instance.
   */
  public LinkActionsEditorPanel() {
  }

  @Override
  public String getTitle() {
    return bundle.getString("linkActionsEditorPanel.title");
  }

  @Override
  protected void edit() {
    String value = getItemsList().getSelectedValue();

    if (value == null) {
      return;
    }

    int index = getItemsList().getSelectedIndex();
    JDialog parent = (JDialog) getTopLevelAncestor();
    SelectionPanel content = new SelectionPanel(
        bundle.getString("linkActionsEditorPanel.dialog_actionSelectionEdit.title"),
        bundle.getString("linkActionsEditorPanel.dialog_actionSelection.label_action.text"),
        getPossibleItems(),
        value);
    StandardDetailsDialog dialog = new StandardDetailsDialog(parent, true, content);
    dialog.setLocationRelativeTo(parent);
    dialog.setVisible(true);

    if (dialog.getReturnStatus() == StandardDetailsDialog.RET_OK) {
      DefaultListModel<String> model = (DefaultListModel<String>) getItemsList().getModel();
      model.setElementAt(content.getValue().toString(), index);
    }
  }

  @Override
  protected void add() {
    JDialog parent = (JDialog) getTopLevelAncestor();
    SelectionPanel content = new SelectionPanel(
        bundle.getString("linkActionsEditorPanel.dialog_actionSelectionAdd.title"),
        bundle.getString("linkActionsEditorPanel.dialog_actionSelection.label_action.text"),
        getPossibleItems());
    StandardDetailsDialog dialog = new StandardDetailsDialog(parent, true, content);
    dialog.setLocationRelativeTo(parent);
    dialog.setVisible(true);

    if (dialog.getReturnStatus() == StandardDetailsDialog.RET_OK) {
      DefaultListModel<String> model = (DefaultListModel<String>) getItemsList().getModel();
      Object value = content.getValue();
      if (value != null) {
        model.addElement(value.toString());
      }
    }
  }

  /**
   * Returns the possible actions that can be executed at a station.
   * The actions are determined by the station type.
   *
   * @return The possible actions.
   */
  private List<String> getPossibleItems() {
    LinkModel ref = (LinkModel) getProperty().getModel();
    LocationTypeModel type = ref.getLocation().getLocationType();

    return new ArrayList<>(type.getPropertyAllowedOperations().getItems());
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/adminwebapi/v1/Version.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.adminwebapi.v1;

import org.opentcs.util.Environment;

/**
 * Describes the version of the running kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Version {

  private String baselineVersion = Environment.getBaselineVersion();

  private String customizationName = Environment.getCustomizationName();

  private String customizationVersion = Environment.getCustomizationVersion();

  public Version() {
  }

  public String getBaselineVersion() {
    return baselineVersion;
  }

  public void setBaselineVersion(String baselineVersion) {
    this.baselineVersion = baselineVersion;
  }

  public String getCustomizationName() {
    return customizationName;
  }

  public void setCustomizationName(String customizationName) {
    this.customizationName = customizationName;
  }

  public String getCustomizationVersion() {
    return customizationVersion;
  }

  public void setCustomizationVersion(String customizationVersion) {
    this.customizationVersion = customizationVersion;
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/PropertyUndoActivity.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import org.opentcs.guing.components.properties.event.NullAttributesChangeListener;
import org.opentcs.guing.components.properties.type.Property;

/**
 * An undo action for a property change.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class PropertyUndoActivity
    extends javax.swing.undo.AbstractUndoableEdit {

  /**
   * The property that changes.
   */
  protected Property fProperty;
  /**
   * The property before the change.
   */
  protected Property fBeforeModification;
  /**
   * The property after the change.
   */
  protected Property fAfterModification;
  /**
   * Indicates whether this change has been performed.
   * Defaults to true; becomes false if this edit is undone, true
   * again if it is redone.
   */
  private boolean hasBeenDone = true;
  /**
   * True if this edit has not received <code>die</code>; defaults
   * to <code>true</code>.
   */
  private boolean alive = true;

  /**
   * Creates a new instance of PropertiesUndoActivity
   *
   * @param property
   */
  public PropertyUndoActivity(Property property) {
    fProperty = property;
  }

  /**
   * Creates a snapshot of the property before the change.
   */
  public void snapShotBeforeModification() {
    fBeforeModification = createMemento();
  }

  /**
   * Creates a snapshot of the property after the change.
   */
  public void snapShotAfterModification() {
    fAfterModification = createMemento();
  }

  /**
   * Creates a copy of the current state of the property.
   *
   * @return A copy of the current state of the property.
   */
  protected Property createMemento() {
    return (Property) fProperty.clone();
  }

  @Override
  public String getPresentationName() {
    return fProperty.getDescription();
  }

  @Override
  public void die() {
    alive = false;
  }

  @Override
  public void undo()
      throws CannotUndoException {
    fProperty.copyFrom(fBeforeModification);
    fProperty.markChanged();
    fProperty.getModel().propertiesChanged(new NullAttributesChangeListener());
    hasBeenDone = false;
  }

  @Override
  public void redo()
      throws CannotRedoException {
    fProperty.copyFrom(fAfterModification);
    fProperty.markChanged();
    fProperty.getModel().propertiesChanged(new NullAttributesChangeListener());
    hasBeenDone = true;
  }

  @Override
  public boolean canUndo() {
    return alive && hasBeenDone;
  }

  @Override
  public boolean canRedo() {
    return alive && !hasBeenDone;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/TransportOrderSelectionFilter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection;

import java.util.Collection;
import java.util.function.Function;
import org.opentcs.data.order.TransportOrder;

/**
 * A filter for {@link TransportOrder}s.
 * Returns a collection of reasons for filtering the transport order.
 * If the returned collection is empty, no reason to filter it was encountered.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface TransportOrderSelectionFilter
    extends Function<TransportOrder, Collection<String>> {
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/StandardPropertyCellRenderer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JLabel;
import javax.swing.JTable;
import org.opentcs.guing.components.properties.type.AbstractProperty;
import org.opentcs.guing.components.properties.type.AcceptableInvalidValue;
import org.opentcs.guing.components.properties.type.BooleanProperty;
import org.opentcs.guing.components.properties.type.MultipleDifferentValues;
import org.opentcs.guing.components.properties.type.Property;

/**
 * A standard cell renderer for for properties in general.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class StandardPropertyCellRenderer
    extends javax.swing.table.DefaultTableCellRenderer {

  public final static Color BG_UNEDITABLE = new Color(0xE0E0E0);

  /**
   * Creates a new instance of StringPropertyCellRenderer
   */
  public StandardPropertyCellRenderer() {
    super();
    setStyle();
  }

  /**
   * Initialises the style fo the labels.
   */
  protected final void setStyle() {
    setFont(new Font("Dialog", Font.PLAIN, 12));
    setHorizontalAlignment(JLabel.LEFT);
    setBorder(null);
  }

  /**
   * Returns a component with the visualisation for this property.
   *
   * @return a component with the visualisation for this property.
   */
  @Override
  public Component getTableCellRendererComponent(
      JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected,
                                                                hasFocus, row, column);
    label.setText(value.toString());

    if (value instanceof AbstractProperty
        && ((AbstractProperty) value).getValue() instanceof AcceptableInvalidValue) {
      AbstractProperty property = (AbstractProperty) value;
      AcceptableInvalidValue invalidValue = (AcceptableInvalidValue) property.getValue();
      label.setText(invalidValue.getDescription());
      label.setToolTipText(invalidValue.getHelptext());
    }
    else if (value instanceof Property) {
      label.setToolTipText(((Property) value).getHelptext());
    }

    decorate(table, row, column, label, value);

    return this;
  }

  protected void decorate(JTable table, int row, int column, JLabel label, Object value) {
    AttributesTable attributesTable = (AttributesTable) table;
    boolean editable = attributesTable.isEditable(row);

    switch (column) {
      case 0:
        label.setBackground(BG_UNEDITABLE);
        label.setForeground(Color.darkGray);
        break;

      case 1:
        if (value instanceof MultipleDifferentValues) {
          label.setBackground(AbstractPropertyCellEditor.DIFFERENT_VALUE_COLOR);
        }
        else {
          label.setBackground(editable ? Color.white : BG_UNEDITABLE);
        }
        label.setForeground(editable ? Color.blue : Color.darkGray);
        break;

      default:
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/drawing/ViewDragScrollListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.awt.Container;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.swing.JComboBox;
import javax.swing.JToggleButton;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.opentcs.data.model.Vehicle;
import org.opentcs.guing.application.StatusPanel;
import org.opentcs.guing.components.drawing.figures.FigureConstants;
import org.opentcs.guing.components.drawing.figures.LabeledLocationFigure;
import org.opentcs.guing.components.drawing.figures.LabeledPointFigure;
import org.opentcs.guing.components.drawing.figures.PathConnection;
import org.opentcs.guing.components.drawing.figures.VehicleFigure;
import org.opentcs.guing.components.drawing.figures.liner.TripleBezierLiner;
import org.opentcs.guing.components.drawing.figures.liner.TupelBezierLiner;
import org.opentcs.guing.exchange.TransportOrderUtil;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.Cursors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A listener for dragging of the drawing view and single objects inside the
 * view.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewDragScrollListener
    extends MouseAdapter {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ViewDragScrollListener.class);
  /**
   * The scroll pane enclosing the drawing view.
   */
  private final DrawingViewScrollPane scrollPane;
  /**
   * The combo box for selecting the zoom level.
   */
  private final JComboBox<ZoomItem> zoomComboBox;
  /**
   * The button for enabling object selection.
   */
  private final JToggleButton selectionTool;
  /**
   * The button for enabling dragging.
   */
  private final JToggleButton dragTool;
  /**
   * The status panel to display the current mouse position in.
   */
  private final StatusPanel statusPanel;
  /**
   * The manager keeping/providing the currently loaded model.
   */
  private final ModelManager modelManager;
  /**
   * A helper for creating transport orders.
   */
  private final TransportOrderUtil orderUtil;
  /**
   * A default cursor for the drawing view.
   */
  private final Cursor defaultCursor;
  /**
   * The start position of drag movements.
   */
  private final Point startPoint = new Point();
  /**
   * Start coordinate for measuring.
   * XXX Is this redundant, or is it used for something different than startPoint?
   */
  private final Point2D.Double fMouseStartPoint = new Point2D.Double();
  /**
   * Current coordinate for measuring.
   */
  private final Point2D.Double fMouseCurrentPoint = new Point2D.Double();
  /**
   * End coordinate for measuring.
   */
  private final Point2D.Double fMouseEndPoint = new Point2D.Double();
  /**
   * The figure a user may have pressed on / want to drag.
   */
  private Figure pressedFigure;

  /**
   * Creates a new instance.
   *
   * @param scrollPane The scroll pane enclosing the drawing view.
   * @param zoomComboBox The combo box for selecting the zoom level.
   * @param selectionTool The button for enabling object selection.
   * @param dragTool The button for enabling dragging.
   * @param statusPanel The status panel to display the current mouse position in.
   * @param modelManager The manager keeping/providing the currently loaded model.
   * @param orderUtil A helper for creating transport orders.
   */
  public ViewDragScrollListener(DrawingViewScrollPane scrollPane,
                                JComboBox<ZoomItem> zoomComboBox,
                                JToggleButton selectionTool,
                                JToggleButton dragTool,
                                StatusPanel statusPanel,
                                ModelManager modelManager,
                                TransportOrderUtil orderUtil) {
    this.scrollPane = requireNonNull(scrollPane, "scrollPane");
    this.zoomComboBox = requireNonNull(zoomComboBox, "zoomComboBox");
    this.selectionTool = requireNonNull(selectionTool, "selectionTool");
    this.dragTool = requireNonNull(dragTool, "dragTool");
    this.statusPanel = requireNonNull(statusPanel, "statusPanel");
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.orderUtil = requireNonNull(orderUtil, "orderUtil");
    this.defaultCursor = scrollPane.getDrawingView().getComponent().getCursor();
  }

  @Override
  public void mouseDragged(final MouseEvent evt) {
    final DrawingView drawingView = scrollPane.getDrawingView();
    if (vehicleDragged()) {
      drawingView.setCursor(Cursors.getDragVehicleCursor());
    }

    if (!(drawingView.getComponent().getParent() instanceof JViewport)) {
      return;
    }

    final JViewport viewport = (JViewport) drawingView.getComponent().getParent();
    Point cp = SwingUtilities.convertPoint(drawingView.getComponent(), evt.getPoint(), viewport);

    if (dragTool.isSelected()) {
      int dx = startPoint.x - cp.x;
      int dy = startPoint.y - cp.y;
      Point vp = viewport.getViewPosition();
      vp.translate(dx, dy);
      drawingView.getComponent().scrollRectToVisible(new Rectangle(vp, viewport.getSize()));
    }
    else { // The selection tool is selected
      viewport.revalidate();

      if (isMovableFigure(pressedFigure)) {
        if (!isFigureCompletelyInView(pressedFigure, viewport, drawingView)) {
          // If the figure exceeds the current view, start scrolling as soon as the mouse is 
          // hitting the view bounds.
          drawingView.getComponent().scrollRectToVisible(new Rectangle(evt.getX(), evt.getY(), 1, 1));
        }

        fMouseCurrentPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
        showPositionStatus(false);
        startPoint.setLocation(cp);
      }
    }
    SwingUtilities.invokeLater(() -> {
      Rectangle2D.Double drawingArea = drawingView.getDrawing().getDrawingArea();
      scrollPane.getHorizontalRuler().setPreferredWidth((int) drawingArea.width);
      scrollPane.getVerticalRuler().setPreferredHeight((int) drawingArea.height);
    });
  }

  private boolean isMovableFigure(Figure figure) {
    return (figure instanceof LabeledPointFigure)
        || (figure instanceof LabeledLocationFigure)
        || ((figure instanceof PathConnection)
            && (((PathConnection) figure).getLiner() instanceof TupelBezierLiner))
        || ((figure instanceof PathConnection)
            && (((PathConnection) figure).getLiner() instanceof TripleBezierLiner));
  }

  private boolean isFigureCompletelyInView(Figure figure,
                                           JViewport viewport,
                                           DrawingView drawingView) {
    Rectangle viewPortBounds = viewport.getViewRect();
    Rectangle figureBounds = drawingView.drawingToView(figure.getDrawingArea());

    return (figureBounds.getMinX() > viewPortBounds.getMinX())
        && (figureBounds.getMinY() > viewPortBounds.getMinY())
        && (figureBounds.getMaxX() < viewPortBounds.getMaxX())
        && (figureBounds.getMaxY() < viewPortBounds.getMaxY());
  }

  @Override
  public void mousePressed(MouseEvent evt) {
    final DrawingView drawingView = scrollPane.getDrawingView();
    if (dragIsSelected()) {
      drawingView.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
    }
    Container c = drawingView.getComponent().getParent();
    if (c instanceof JViewport) {
      JViewport viewPort = (JViewport) c;
      Point cp = SwingUtilities.convertPoint(drawingView.getComponent(), evt.getPoint(), viewPort);
      startPoint.setLocation(cp);
    }
    pressedFigure = drawingView.findFigure(evt.getPoint());
    fMouseCurrentPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
    fMouseStartPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
    showPositionStatus(false);
  }

  @Override
  public void mouseReleased(MouseEvent evt) {
    if (dragIsSelected()) {
      return;
    }

    final DrawingView drawingView = scrollPane.getDrawingView();
    Figure fig = drawingView.findFigure(evt.getPoint());
    if (fig instanceof LabeledPointFigure) {
      createPossibleTransportOrder((LabeledPointFigure) fig, drawingView.getSelectedFigures());
    }
    pressedFigure = null;
    fMouseEndPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
    if (evt.getButton() != 2) {
      showPositionStatus(true);
    }
    else {
      showPositionStatus(false);
    }
  }

  @Override
  public void mouseExited(MouseEvent evt) {
    dragIsSelected();
    clearPositionStatus();
  }

  @Override
  public void mouseEntered(MouseEvent evt) {
    dragIsSelected();
  }

  @Override
  public void mouseMoved(MouseEvent evt) {
    final DrawingView drawingView = scrollPane.getDrawingView();
    fMouseCurrentPoint.setLocation(drawingView.viewToDrawing(evt.getPoint()));
    showPositionStatus(false);
  }

  @Override
  public void mouseClicked(MouseEvent evt) {
    if (evt.getButton() == 2) {
      if (dragTool.isSelected()) {
        selectionTool.setSelected(true);
      }
      else if (selectionTool.isSelected()) {
        dragTool.setSelected(true);
      }
      // Sets the correct cursor
      dragIsSelected();
    }
  }

  @Override
  public void mouseWheelMoved(MouseWheelEvent e) {
    if (e.isControlDown()) {
      int zoomLevel = zoomComboBox.getSelectedIndex();
      int notches = e.getWheelRotation();
      if (zoomLevel != -1) {
        if (notches < 0) {
          if (zoomLevel > 0) {
            zoomLevel--;
            zoomComboBox.setSelectedIndex(zoomLevel);
          }
        }
        else {
          if (zoomLevel < zoomComboBox.getItemCount() - 1) {
            zoomLevel++;
            zoomComboBox.setSelectedIndex(zoomLevel);
          }
        }
      }
    }
  }

  /**
   * Checks whether the drag tool is selected.
   *
   * @return true if the drag tool is selected, false otherwise.
   */
  private boolean dragIsSelected() {
    final DrawingView drawingView = scrollPane.getDrawingView();
    if (!selectionTool.isSelected() && dragTool.isSelected()) {
      drawingView.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
      return true;
    }
    else if (selectionTool.isSelected() && !dragTool.isSelected()) {
      drawingView.setCursor(defaultCursor);
      return false;
    }
    else {
      return false;
    }
  }

  /**
   * Clears the mouse position information in the status panel.
   */
  private void clearPositionStatus() {
    statusPanel.setPositionText("");
  }

  /**
   * Displays the current mouse position or covered area in the status panel.
   *
   * @param showCoveredArea Whether to display the dimensions of the covered
   * area instead of the current mouse coordinates.
   */
  private void showPositionStatus(boolean showCoveredArea) {
    double x = fMouseCurrentPoint.x;
    double y = -fMouseCurrentPoint.y;

    if (showCoveredArea) {
      double w = Math.abs(fMouseEndPoint.x - fMouseStartPoint.x);
      double h = Math.abs(fMouseEndPoint.y - fMouseStartPoint.y);
      statusPanel.setPositionText(
          String.format("X %.0f Y %.0f W %.0f H %.0f", x, y, w, h));
    }
    else {
      LayoutModel layout = modelManager.getModel().getLayoutModel();

      double scaleX = (double) layout.getPropertyScaleX().getValue();
      double scaleY = (double) layout.getPropertyScaleY().getValue();
      double xmm = x * scaleX;
      double ymm = y * scaleY;
      statusPanel.setPositionText(
          String.format("X %.0f (%.0fmm) Y %.0f (%.0fmm)", x, xmm, y, ymm));
    }
  }

  /**
   * Creates a transport order, assuming a single vehicle was selected before.
   *
   * @param figure A point figure.
   */
  private void createPossibleTransportOrder(LabeledPointFigure figure,
                                            Set<Figure> selectedFigures) {
    if (selectedFigures.size() != 1) {
      LOG.debug("More than one figure selected, skipping.");
      return;
    }

    Figure nextFigure = selectedFigures.iterator().next();

    if (!(nextFigure instanceof VehicleFigure)) {
      LOG.debug("Selected figure is not a VehicleFigure, skipping.");
      return;
    }

    PointModel model = figure.getPresentationFigure().getModel();
    VehicleModel vehicleModel = (VehicleModel) nextFigure.get(FigureConstants.MODEL);

    if (vehicleModel == null) {
      LOG.warn("Selected VehicleFigure does not have a model, skipping.");
      return;
    }
    if ((Vehicle.ProcState) vehicleModel.getPropertyProcState().getValue() != Vehicle.ProcState.IDLE) {
      LOG.debug("Selected vehicle already has an order, skipping.");
      return;
    }

    orderUtil.createTransportOrder(model, vehicleModel);
  }

  /**
   * Returns if a vehicle is currently being dragged.
   *
   * @return True if yes, false otherwise.
   */
  private boolean vehicleDragged() {
    Set<Figure> selectedFigures = scrollPane.getDrawingView().getSelectedFigures();
    if (selectedFigures.size() != 1) {
      return false;
    }

    return selectedFigures.iterator().next() instanceof VehicleFigure;
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/SslConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the ssl connection.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(SslConfiguration.PREFIX)
public interface SslConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "ssl";

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to use SSL to encrypt RMI connections to the kernel.",
      orderKey = "0_connection_0")
  boolean enable();

  @ConfigurationEntry(
      type = "String",
      description = "The path to the SSL truststore.",
      orderKey = "0_connection_1")
  String truststoreFile();

  @ConfigurationEntry(
      type = "String",
      description = "The password for the SSL truststore.",
      orderKey = "0_connection_2")
  String truststorePassword();
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/ObjectHistoryEntryFormatter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.util.Optional;
import java.util.function.Function;
import org.opentcs.data.ObjectHistory;

/**
 * A formatter for {@link ObjectHistory} entries, mapping an entry to a user-presentable string, if
 * possible.
 * Indicates that it cannot map an entry by returning an empty {@code Optional}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ObjectHistoryEntryFormatter
    extends Function<ObjectHistory.Entry, Optional<String>> {

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/Point.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * Describes a position in the driving course at which a {@link Vehicle} may be located.
 *
 * @see Path
 * @author <NAME> (Fraunhofer IML)
 */
public class Point
    extends TCSResource<Point>
    implements Serializable {

  /**
   * This point's coordinates in mm.
   */
  private final Triple position;
  /**
   * This point's type.
   */
  private final Type type;
  /**
   * The vehicle's (assumed) orientation angle (-360..360) when it is at this
   * position.
   * May be Double.NaN if an orientation angle is not defined for this point.
   */
  private final double vehicleOrientationAngle;
  /**
   * A set of references to paths ending in this point.
   */
  private final Set<TCSObjectReference<Path>> incomingPaths;
  /**
   * A set of references to paths originating in this point.
   */
  private final Set<TCSObjectReference<Path>> outgoingPaths;
  /**
   * A set of links attached to this point.
   */
  private final Set<Location.Link> attachedLinks;
  /**
   * A reference to the vehicle occupying this point.
   */
  private final TCSObjectReference<Vehicle> occupyingVehicle;
  /**
   * The information regarding the grahical representation of this point.
   */
  private final Layout layout;

  /**
   * Creates a new point with the given name.
   *
   * @param name This point's name.
   */
  public Point(String name) {
    super(name);
    this.position = new Triple(0, 0, 0);
    this.type = Type.HALT_POSITION;
    this.vehicleOrientationAngle = Double.NaN;
    this.incomingPaths = new HashSet<>();
    this.outgoingPaths = new HashSet<>();
    this.attachedLinks = new HashSet<>();
    this.occupyingVehicle = null;
    this.layout = new Layout();
  }

  private Point(String name,
                Map<String, String> properties,
                ObjectHistory history,
                Triple position,
                Type type,
                double vehicleOrientationAngle,
                Set<TCSObjectReference<Path>> incomingPaths,
                Set<TCSObjectReference<Path>> outgoingPaths,
                Set<Location.Link> attachedLinks,
                TCSObjectReference<Vehicle> occupyingVehicle,
                Layout layout) {
    super(name, properties, history);
    this.position = requireNonNull(position, "position");
    this.type = requireNonNull(type, "type");
    checkArgument(Double.isNaN(vehicleOrientationAngle)
        || (vehicleOrientationAngle >= -360.0 && vehicleOrientationAngle <= 360.0),
                  "angle not in [-360..360]: %s",
                  vehicleOrientationAngle);
    this.vehicleOrientationAngle = vehicleOrientationAngle;
    this.incomingPaths = setWithoutNullValues(requireNonNull(incomingPaths, "incomingPaths"));
    this.outgoingPaths = setWithoutNullValues(requireNonNull(outgoingPaths, "outgoingPaths"));
    this.attachedLinks = setWithoutNullValues(requireNonNull(attachedLinks, "attachedLinks"));
    this.occupyingVehicle = occupyingVehicle;
    this.layout = requireNonNull(layout, "layout");
  }

  @Override
  public Point withProperty(String key, String value) {
    return new Point(getName(),
                     propertiesWith(key, value),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  @Override
  public Point withProperties(Map<String, String> properties) {
    return new Point(getName(),
                     properties,
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  @Override
  public TCSObject<Point> withHistoryEntry(ObjectHistory.Entry entry) {
    return new Point(getName(),
                     getProperties(),
                     getHistory().withEntryAppended(entry),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  @Override
  public TCSObject<Point> withHistory(ObjectHistory history) {
    return new Point(getName(),
                     getProperties(),
                     history,
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns the physical coordinates of this point in mm.
   *
   * @return The physical coordinates of this point in mm.
   */
  public Triple getPosition() {
    return position;
  }

  /**
   * Creates a copy of this object, with the given position.
   *
   * @param position The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withPosition(Triple position) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns a vehicle's orientation angle at this position.
   * (-360..360, or <code>Double.NaN</code>, if an orientation angle is not
   * specified for this point.)
   *
   * @return The vehicle's orientation angle when it's at this position.
   */
  public double getVehicleOrientationAngle() {
    return vehicleOrientationAngle;
  }

  /**
   * Creates a copy of this object, with the given vehicle orientation angle.
   *
   * @param vehicleOrientationAngle The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withVehicleOrientationAngle(double vehicleOrientationAngle) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns this point's type.
   *
   * @return This point's type.
   */
  public Type getType() {
    return type;
  }

  /**
   * Creates a copy of this object, with the given type.
   *
   * @param type The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withType(Type type) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Checks whether parking a vehicle on this point is allowed.
   * <p>
   * This method is a convenience method; its return value is equal to
   * <code>getType().equals(Point.Type.PARK_POSITION)</code>.
   * </p>
   *
   * @return <code>true</code> if, and only if, parking is allowed on this
   * point.
   */
  public boolean isParkingPosition() {
    return type.equals(Type.PARK_POSITION);
  }

  /**
   * Checks whether halting on this point is allowed.
   * <p>
   * This method is a convenience method; its return value is equal to
   * <code>getType().equals(Point.Type.PARK_POSITION) ||
   * getType().equals(Point.Type.HALT_POSITION)</code>.
   * </p>
   *
   * @return <code>true</code> if, and only if, halting is allowed on this
   * point.
   */
  public boolean isHaltingPosition() {
    return type.equals(Type.PARK_POSITION) || type.equals(Type.HALT_POSITION);
  }

  /**
   * Returns a reference to the vehicle occupying this point.
   *
   * @return A reference to the vehicle occupying this point, or
   * <code>null</code>, if this point isn't currently occupied by any vehicle.
   */
  public TCSObjectReference<Vehicle> getOccupyingVehicle() {
    return occupyingVehicle;
  }

  /**
   * Creates a copy of this object, with the given occupying vehicle.
   *
   * @param occupyingVehicle The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withOccupyingVehicle(TCSObjectReference<Vehicle> occupyingVehicle) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns a set of references to paths ending in this point.
   *
   * @return A set of references to paths ending in this point.
   */
  public Set<TCSObjectReference<Path>> getIncomingPaths() {
    return Collections.unmodifiableSet(incomingPaths);
  }

  /**
   * Creates a copy of this object, with the given incoming paths.
   *
   * @param incomingPaths The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withIncomingPaths(Set<TCSObjectReference<Path>> incomingPaths) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns a set of references to paths originating in this point.
   *
   * @return A set of references to paths originating in this point.
   */
  public Set<TCSObjectReference<Path>> getOutgoingPaths() {
    return Collections.unmodifiableSet(outgoingPaths);
  }

  /**
   * Creates a copy of this object, with the given outgoing paths.
   *
   * @param outgoingPaths The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withOutgoingPaths(Set<TCSObjectReference<Path>> outgoingPaths) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns a set of links attached to this point.
   *
   * @return A set of links attached to this point.
   */
  public Set<Location.Link> getAttachedLinks() {
    return Collections.unmodifiableSet(attachedLinks);
  }

  /**
   * Creates a copy of this object, with the given attached links.
   *
   * @param attachedLinks The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withAttachedLinks(Set<Location.Link> attachedLinks) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Returns the information regarding the grahical representation of this point.
   *
   * @return The information regarding the grahical representation of this point.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Point withLayout(Layout layout) {
    return new Point(getName(),
                     getProperties(),
                     getHistory(),
                     position,
                     type,
                     vehicleOrientationAngle,
                     incomingPaths,
                     outgoingPaths,
                     attachedLinks,
                     occupyingVehicle,
                     layout);
  }

  /**
   * Describes the types of positions in a driving course.
   */
  public enum Type {

    /**
     * Indicates a position at which a vehicle is expected to report in.
     * Halting or even parking at such a position is not allowed.
     */
    REPORT_POSITION,
    /**
     * Indicates a position at which a vehicle may halt temporarily, e.g. for executing an
     * operation.
     * The vehicle is also expected to report in when it arrives at such a position.
     * It may not park here for longer than necessary, though.
     */
    HALT_POSITION,
    /**
     * Indicates a position at which a vehicle may halt for longer periods of time when it is not
     * processing orders.
     * The vehicle is also expected to report in when it arrives at such a position.
     */
    PARK_POSITION;
  }

  /**
   * Contains information regarding the grahical representation of a point.
   */
  public static class Layout
      implements Serializable {

    /**
     * The coordinates at which the point is to be drawn (in mm).
     */
    private final Couple position;
    /**
     * The offset of the label's position to the point's position (in lu).
     */
    private final Couple labelOffset;
    /**
     * The ID of the layer on which the point is to be drawn.
     */
    private final int layerId;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(new Couple(0, 0), new Couple(0, 0), 0);
    }

    /**
     * Creates a new instance.
     *
     * @param position The coordinates at which the point is to be drawn (in mm).
     * @param labelOffset The offset of the label's position to the point's position (in lu).
     * @param layerId The ID of the layer on which the point is to be drawn.
     */
    public Layout(Couple position,
                  Couple labelOffset,
                  int layerId) {
      this.position = requireNonNull(position, "position");
      this.labelOffset = requireNonNull(labelOffset, "labelOffset");
      this.layerId = layerId;
    }

    /**
     * Returns the coordinates at which the point is to be drawn (in mm).
     *
     * @return The coordinates at which the point is to be drawn (in mm).
     */
    public Couple getPosition() {
      return position;
    }

    /**
     * Creates a copy of this object, with the given position.
     *
     * @param position The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withPosition(Couple position) {
      return new Layout(position,
                        labelOffset,
                        layerId);
    }

    /**
     * Returns the offset of the label's position to the point's position (in lu).
     *
     * @return The offset of the label's position to the point's position (in lu).
     */
    public Couple getLabelOffset() {
      return labelOffset;
    }

    /**
     * Creates a copy of this object, with the given X label offset.
     *
     * @param labelOffset The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLabelOffset(Couple labelOffset) {
      return new Layout(position,
                        labelOffset,
                        layerId);
    }

    /**
     * Returns the ID of the layer on which the point is to be drawn.
     *
     * @return The layer ID.
     */
    public int getLayerId() {
      return layerId;
    }

    /**
     * Creates a copy of this object, with the given layer ID.
     *
     * @param layerId The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLayerId(int layerId) {
      return new Layout(position,
                        labelOffset,
                        layerId);
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/menus/menubar/ViewMenu.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.application.action.view.AddDrawingViewAction;
import org.opentcs.guing.application.action.view.AddTransportOrderSequenceViewAction;
import org.opentcs.guing.application.action.view.AddTransportOrderViewAction;
import org.opentcs.guing.application.action.view.RestoreDockingLayoutAction;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * The application's menu for view-related operations.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ViewMenu
    extends JMenu {

  /**
   * A menu item for adding a drawing view.
   */
  private final JMenuItem menuAddDrawingView;
  /**
   * A menu item for adding a transport order view.
   */
  private final JMenuItem menuTransportOrderView;
  /**
   * A menu item for adding an order sequence view.
   */
  private final JMenuItem menuOrderSequenceView;
  /**
   * A menu for showing/hiding plugin panels.
   */
  private final ViewPluginPanelsMenu menuPluginPanels;
  /**
   * A menu item for restoring the default GUI layout.
   */
  private final JMenuItem menuItemRestoreDockingLayout;

  /**
   * Creates a new instance.
   *
   * @param actionMap The application's action map.
   * @param menuPluginPanels A menu for showing/hiding plugin panels.
   */
  @Inject
  public ViewMenu(ViewActionMap actionMap,
                  ViewPluginPanelsMenu menuPluginPanels) {
    requireNonNull(actionMap, "actionMap");
    requireNonNull(menuPluginPanels, "menuPluginPanels");

    final ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.MENU_PATH);

    this.setText(labels.getString("viewMenu.text"));
    this.setToolTipText(labels.getString("viewMenu.tooltipText"));
    this.setMnemonic('V');

    // Menu item View -> Add course view
    menuAddDrawingView = new JMenuItem(actionMap.get(AddDrawingViewAction.ID));
    add(menuAddDrawingView);

    // Menu item View -> Add transport order view
    menuTransportOrderView = new JMenuItem(actionMap.get(AddTransportOrderViewAction.ID));
    add(menuTransportOrderView);

    // Menu item View -> Add transport order sequence view
    menuOrderSequenceView = new JMenuItem(actionMap.get(AddTransportOrderSequenceViewAction.ID));
    add(menuOrderSequenceView);

    addSeparator();

    // Menu item View -> Plugins
    this.menuPluginPanels = menuPluginPanels;
    menuPluginPanels.setOperationMode(OperationMode.OPERATING);
    add(menuPluginPanels);

    // Menu item View -> Restore docking layout
    menuItemRestoreDockingLayout = new JMenuItem(actionMap.get(RestoreDockingLayoutAction.ID));
    menuItemRestoreDockingLayout.setText(labels.getString("viewMenu.menuItem_restoreWindowArrangement.text"));
    add(menuItemRestoreDockingLayout);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/PeripheralJobUtil.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.InternalPeripheralJobService;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralControllerPool;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides service functions for working with peripheral jobs and their states.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralJobUtil {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralJobUtil.class);
  /**
   * The peripheral service to use.
   */
  private final InternalPeripheralService peripheralService;
  /**
   * The peripheral job service to use.
   */
  private final InternalPeripheralJobService peripheralJobService;
  /**
   * The peripheral controller pool.
   */
  private final PeripheralControllerPool peripheralControllerPool;
  /**
   * The peripheral job callback to use.
   */
  private final PeripheralJobCallback peripheralJobCallback;

  @Inject
  public PeripheralJobUtil(InternalPeripheralService peripheralService,
                           InternalPeripheralJobService peripheralJobService,
                           PeripheralControllerPool peripheralControllerPool,
                           PeripheralJobCallback peripheralJobCallback) {
    this.peripheralService = requireNonNull(peripheralService, "peripheralService");
    this.peripheralJobService = requireNonNull(peripheralJobService, "peripheralJobService");
    this.peripheralControllerPool = requireNonNull(peripheralControllerPool,
                                                   "peripheralControllerPool");
    this.peripheralJobCallback = requireNonNull(peripheralJobCallback, "peripheralJobCallback");
  }

  public void assignPeripheralJob(Location location, PeripheralJob peripheralJob) {
    requireNonNull(location, "location");
    requireNonNull(peripheralJob, "peripheralJob");

    LOG.debug("Assigning location {} to job {}.", location.getName(), peripheralJob.getName());
    final TCSResourceReference<Location> locationRef = location.getReference();
    final TCSObjectReference<PeripheralJob> jobRef = peripheralJob.getReference();
    // Set the locations's and peripheral job's state.
    peripheralService.updatePeripheralProcState(locationRef,
                                                PeripheralInformation.ProcState.PROCESSING_JOB);
    peripheralService.updatePeripheralReservationToken(locationRef,
                                                       peripheralJob.getReservationToken());
    peripheralService.updatePeripheralJob(locationRef, jobRef);
    peripheralJobService.updatePeripheralJobState(jobRef, PeripheralJob.State.BEING_PROCESSED);

    peripheralControllerPool.getPeripheralController(locationRef).process(peripheralJob,
                                                                          peripheralJobCallback);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/jgrapht/BellmanFordPointRouterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.jgrapht;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.jgrapht.Graph;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
import org.jgrapht.alg.shortestpath.BellmanFordShortestPath;
import org.opentcs.components.kernel.routing.Edge;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.strategies.basic.routing.PointRouter;

/**
 * Creates {@link PointRouter} instances based on the Bellman-Ford algorithm.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class BellmanFordPointRouterFactory
    extends AbstractPointRouterFactory {

  /**
   * Creates a new instance.
   *
   * @param objectService The object service providing model data.
   * @param mapper Maps the plant model to a graph.
   */
  @Inject
  public BellmanFordPointRouterFactory(@Nonnull TCSObjectService objectService,
                                       @Nonnull ModelGraphMapper mapper) {
    super(objectService, mapper);
  }

  @Override
  protected ShortestPathAlgorithm<String, Edge> createShortestPathAlgorithm(
      Graph<String, Edge> graph) {
    return new BellmanFordShortestPath<>(graph);
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/SortableTreeNode.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree;

import java.util.Collections;
import java.util.Comparator;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import org.slf4j.LoggerFactory;

/**
 * A tree node that can be sorted.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class SortableTreeNode
    extends DefaultMutableTreeNode {

  /**
   * True if the child elements of this node can be sorted.
   */
  private boolean fSorting;

  /**
   * Creates a new instance.
   *
   * @param userObject The UserObject.
   */
  public SortableTreeNode(Object userObject) {
    super(userObject);
    setSorting(true);
  }

  /**
   * Sets whether or not the child elements of this node can be sorted.
   *
   * @param sorting True if the child elements of this node can be sorted.
   */
  public final void setSorting(boolean sorting) {
    fSorting = sorting;
  }

  /**
   * Returns true if the child elements of this node can be sorted.
   * 
   * @return True if the child elements of this node can be sorted.
   */
  public boolean isSorting() {
    return fSorting;
  }

  /**
   * Sort the child elements.
   *
   * @param comparator The comparator to be used for sorting.
   */
  @SuppressWarnings("unchecked")
  public void sort(Comparator<Object> comparator) {
    Collections.sort(children, comparator);
  }

  @Override
  public TreeNode getChildAt(int index) {
    try {
      return super.getChildAt(index);
    }
    catch (ArrayIndexOutOfBoundsException e) {
      // XXX remove if never observed
      LoggerFactory.getLogger(SortableTreeNode.class)
          .error("Exception while calling SortableTreeNode.getChildAt()", e);
      return null;
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/management/PeripheralAttachmentEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals.management;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;

/**
 * Instances of this class represent events emitted by/for attaching comm adapters.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralAttachmentEvent
    extends PeripheralCommAdapterEvent
    implements Serializable {

  /**
   * The location a peripheral comm adapter has been attached to.
   */
  private final TCSResourceReference<Location> location;
  /**
   * The information to the actual attachment.
   */
  private final PeripheralAttachmentInformation attachmentInformation;

  /**
   * Creates a new instance.
   *
   * @param location The location a comm adapter has been attached to.
   * @param attachmentInformation The information to the actual attachment.
   */
  public PeripheralAttachmentEvent(
      @Nonnull TCSResourceReference<Location> location,
      @Nonnull PeripheralAttachmentInformation attachmentInformation) {
    this.location = requireNonNull(location, "location");
    this.attachmentInformation = requireNonNull(attachmentInformation, "attachmentInformation");
  }

  /**
   * Returns the location a comm adapter has been attached to.
   *
   * @return The location a comm adapter has been attached to.
   */
  public TCSResourceReference<Location> getLocation() {
    return location;
  }

  /**
   * Returns the information to the actual attachment.
   *
   * @return The information to the actual attachment.
   */
  public PeripheralAttachmentInformation getAttachmentInformation() {
    return attachmentInformation;
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/drawing/figures/VehicleFigureFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import org.opentcs.guing.model.elements.VehicleModel;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleFigureFactory
    extends FigureFactory {

  VehicleFigure createVehicleFigure(VehicleModel model);

  NamedVehicleFigure createNamedVehicleFigure(VehicleModel model);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/event/ResetInteractionToolCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.event;

import java.util.EventObject;

/**
 * This event instructs the receiver(s) to reset the currently selected
 * interaction tool for the user.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ResetInteractionToolCommand
    extends EventObject {

  /**
   * Creates a new instance.
   *
   * @param source The event's originator.
   */
  public ResetInteractionToolCommand(Object source) {
    super(source);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/ComponentsManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import java.util.List;
import org.opentcs.guing.components.tree.elements.UserObject;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ComponentsManager {

  /**
   * Adds the given model components to the data model. (e.g. when pasting)
   *
   * @param userObjects The user objects to restore.
   * @return The restored user objects.
   */
  List<UserObject> restoreModelComponents(List<UserObject> userObjects);
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/Streams.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import static java.util.Objects.requireNonNull;
import static org.opentcs.util.Assertions.checkInRange;

/**
 * This class provides helper methods for working with streams.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class Streams {

  /**
   * The initial size for a growing buffer.
   */
  private static final int INITIAL_BUFFER_SIZE = 10000;

  /**
   * Creates a new Streams.
   */
  private Streams() {
  }

  /**
   * Reads an <code>InputStream</code> until it recognizes a given end tag, and
   * returns a new <code>InputStream</code> containing only the bytes up to and
   * including that end tag.
   *
   * @param inStream The stream to read from.
   * @param endTag The sequence of bytes marking the end of the content to be
   * returned.
   * @param includeEndTag Whether or not to include the end tag in the result.
   * @return A new <code>InputStream</code>, containing only the bytes up to and
   * including the end tag, or <code>null</code>, if the end of the stream was
   * reached and no such tag was found. (The bytes read from the stream are
   * discarded.)
   * @throws IOException If an I/O error occurs while reading from the input
   * stream.
   */
  public static InputStream getInputStreamToEndTag(InputStream inStream,
                                                   byte[] endTag,
                                                   boolean includeEndTag)
      throws IOException {
    requireNonNull(inStream, "inStream");
    requireNonNull(endTag, "endTag");
    checkInRange(endTag.length, 1, Integer.MAX_VALUE, "endTag.length");

    SearchableByteArrayOutputStream localBuffer = new SearchableByteArrayOutputStream();
    boolean endTagFound = false;
    int currentByte = inStream.read();
    while (!endTagFound && currentByte != -1) {
      localBuffer.write(currentByte);
      endTagFound = localBuffer.endsWith(endTag);
      currentByte = inStream.read();
    }

    if (endTagFound) {
      ByteArrayInputStream result;
      byte[] input = localBuffer.toByteArray();

      if (includeEndTag) {
        result = new ByteArrayInputStream(input);
      }
      else {
        result = new ByteArrayInputStream(input, 0, input.length - endTag.length);
      }

      return result;
    }
    else {
      return null;
    }
  }

  /**
   * Reads an <code>InputStream</code> to the end and returns an array
   * containing all bytes read.
   * The given <code>InputStream</code> will be closed when this method returns.
   *
   * @param inStream The stream to read from.
   * @return An array containing all bytes read from the given
   * <code>InputStream</code>. If nothing was read, the returned array's length
   * will be 0.
   * @throws IOException If an I/O error occurs while reading from the input
   * stream.
   */
  public static byte[] getCompleteInputStream(InputStream inStream)
      throws IOException {
    requireNonNull(inStream, "inStream");

    int bufferSize = INITIAL_BUFFER_SIZE;
    int offset = 0;
    byte[] buffer = new byte[bufferSize];

    try {
      int bytesRead = inStream.read(buffer, offset, bufferSize - offset);

      while (bytesRead != -1) {
        offset += bytesRead;
        // Enlarge the buffer if it's full.
        if (offset == bufferSize) {
          bufferSize *= 2;
          buffer = Arrays.copyOf(buffer, bufferSize);
        }

        bytesRead = inStream.read(buffer, offset, bufferSize - offset);
      }
    }
    finally {
      inStream.close();
    }
    // Shrink the buffer to the actual size of the data read.
    if (offset < bufferSize) {
      buffer = Arrays.copyOf(buffer, offset);
    }

    return buffer;
  }

  /**
   * A {@code ByteArrayOutputStream} providing additional methods to scan its
   * content for byte sequences.
   */
  private static class SearchableByteArrayOutputStream
      extends ByteArrayOutputStream {

    /**
     * Creates a new SearchableByteArrayOutputStream.
     */
    public SearchableByteArrayOutputStream() {
    }

    /**
     * Checks if this stream currently ends with the given byte sequence.
     *
     * @param endTag The byte sequence to check for.
     * @return {@code true} if, and only if, this stream currently ends with the
     * given byte sequence.
     */
    public boolean endsWith(byte[] endTag) {
      boolean result = false;

      if (count >= endTag.length) {
        result = true;

        for (int i = 1; i <= endTag.length; i++) {
          if (endTag[endTag.length - i] != buf[count - i]) {
            result = false;
            break;
          }
        }
      }

      return result;
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/orders/TransportOrdersContainerPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport.orders;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.data.order.TransportOrder;
import static org.opentcs.data.order.TransportOrder.State.BEING_PROCESSED;
import static org.opentcs.data.order.TransportOrder.State.DISPATCHABLE;
import static org.opentcs.data.order.TransportOrder.State.FAILED;
import static org.opentcs.data.order.TransportOrder.State.FINISHED;
import static org.opentcs.data.order.TransportOrder.State.RAW;
import org.opentcs.guing.components.dialogs.DialogContent;
import org.opentcs.guing.components.dialogs.StandardContentDialog;
import org.opentcs.guing.exchange.TransportOrderUtil;
import org.opentcs.guing.transport.CreateTransportOrderPanel;
import org.opentcs.guing.transport.FilterButton;
import org.opentcs.guing.transport.FilteredRowSorter;
import org.opentcs.guing.transport.OrdersTable;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.guing.util.IconToolkit;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Shows a table of the kernel's transport orders.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrdersContainerPanel
    extends JPanel {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(TransportOrdersContainerPanel.class);
  /**
   * The path containing the icons.
   */
  private static final String ICON_PATH = "/org/opentcs/guing/res/symbols/panel/";
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * A helper for creating transport orders with the kernel.
   */
  private final TransportOrderUtil orderUtil;
  /**
   * Provides panels for entering new transport orders.
   */
  private final Provider<CreateTransportOrderPanel> orderPanelProvider;
  /**
   * A factory for creating transport order views.
   */
  private final TransportViewFactory transportViewFactory;
  /**
   * The table showing the transport orders.
   */
  private JTable fTable;
  /**
   * The table's model.
   */
  private TransportOrderTableModel tableModel;
  /**
   * The sorter for the table.
   */
  private FilteredRowSorter<TransportOrderTableModel> sorter;
  /**
   * Holds the transport orders.
   */
  private final TransportOrdersContainer transportOrdersContainer;

  /**
   * Creates a new instance.
   *
   * @param portalProvider Provides a access to a portal.
   * @param orderUtil A helper for creating transport orders with the kernel.
   * @param orderPanelProvider Provides panels for entering new transport orders.
   * @param transportViewFactory A factory for creating transport order views.
   * @param transportOrderContainer Maintains a set of transport order on the kernel side.
   */
  @Inject
  public TransportOrdersContainerPanel(SharedKernelServicePortalProvider portalProvider,
                                       TransportOrderUtil orderUtil,
                                       Provider<CreateTransportOrderPanel> orderPanelProvider,
                                       TransportViewFactory transportViewFactory,
                                       TransportOrdersContainer transportOrderContainer) {
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.orderUtil = requireNonNull(orderUtil, "orderUtil");
    this.orderPanelProvider = requireNonNull(orderPanelProvider, "orderPanelProvider");
    this.transportViewFactory = requireNonNull(transportViewFactory, "transportViewFactory");
    this.transportOrdersContainer = requireNonNull(transportOrderContainer, "transportOrderContainer");

    initComponents();
  }

  /**
   * Initializes this panel's contents.
   */
  public void initView() {
    tableModel.containerInitialized(transportOrdersContainer.getTransportOrders());
  }

  private void initComponents() {
    setLayout(new BorderLayout());

    tableModel = new TransportOrderTableModel();
    transportOrdersContainer.addListener(tableModel);
    fTable = new OrdersTable(tableModel);
    fTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

    sorter = new FilteredRowSorter<>(tableModel);
    // Sort the table by the creation instant.
    sorter.setSortKeys(Arrays.asList(
        new RowSorter.SortKey(TransportOrderTableModel.COLUMN_CREATION_TIME, SortOrder.DESCENDING)
    ));
    // ...but prevent manual sorting.
    for (int i = 0; i < fTable.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    fTable.setRowSorter(sorter);

    // Hide the column that shows the creation time.
    fTable.removeColumn(fTable.getColumnModel()
        .getColumn(fTable.convertColumnIndexToView(TransportOrderTableModel.COLUMN_CREATION_TIME)));

    JScrollPane scrollPane = new JScrollPane(fTable);
    add(scrollPane, BorderLayout.CENTER);

    JToolBar toolBar = createToolBar(createFilterButtons());
    addControlButtons(toolBar);
    add(toolBar, BorderLayout.NORTH);

    fTable.addMouseListener(new MouseAdapter() {

      @Override
      public void mouseClicked(MouseEvent evt) {
        if (evt.getButton() == MouseEvent.BUTTON1) {
          if (evt.getClickCount() == 2) {
            showSelectedTransportOrder();
          }
        }

        if (evt.getButton() == MouseEvent.BUTTON3) {
          if (fTable.getSelectedRow() != -1) {
            showPopupMenuForSelectedTransportOrder(evt.getX(), evt.getY());
          }
        }
      }
    });
  }

  private void showSelectedTransportOrder() {
    getSelectedTransportOrder().ifPresent(transportOrder -> {
      DialogContent content = transportViewFactory.createTransportOrderView(transportOrder);
      StandardContentDialog dialog
          = new StandardContentDialog(JOptionPane.getFrameForComponent(this),
                                      content,
                                      true,
                                      StandardContentDialog.CLOSE);
      dialog.setTitle(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TODETAIL_PATH)
          .getString("transportOrdersContainerPanel.dialog_createTransportOrder.title"));
      dialog.setVisible(true);
    });
  }

  private void createTransportOrderWithPattern() {
    getSelectedTransportOrder().ifPresent(transportOrder -> {
      CreateTransportOrderPanel content = orderPanelProvider.get();
      content.setPattern(transportOrder);
      StandardContentDialog dialog
          = new StandardContentDialog(JOptionPane.getFrameForComponent(this),
                                      content);
      dialog.setVisible(true);

      if (dialog.getReturnStatus() == StandardContentDialog.RET_OK) {
        orderUtil.createTransportOrder(content.getDestinationModels(),
                                       content.getActions(),
                                       content.getPropertiesList(),
                                       content.getSelectedDeadline(),
                                       content.getSelectedVehicle(),
                                       content.getSelectedType());
      }
    });
  }

  private void createCopyOfSelectedTransportOrder() {
    getSelectedTransportOrder().ifPresent(
        transportOrder -> orderUtil.createTransportOrder(transportOrder)
    );
  }

  private void showPopupMenuForSelectedTransportOrder(int x, int y) {
    boolean singleRowSelected = fTable.getSelectedRowCount() <= 1;
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TRANSPORTORDER_PATH);
    JPopupMenu menu = new JPopupMenu();
    JMenuItem item = menu.add(bundle.getString("transportOrdersContainerPanel.table_orders.popupMenuItem_showDetails.text"));
    item.setEnabled(singleRowSelected);
    item.addActionListener((ActionEvent evt) -> showSelectedTransportOrder());

    menu.add(new JSeparator());

    item = menu.add(bundle.getString("transportOrdersContainerPanel.table_orders.popupMenuItem_orderAsTemplate.text"));
    item.setEnabled(singleRowSelected);
    item.addActionListener((ActionEvent evt) -> createTransportOrderWithPattern());

    item = menu.add(bundle.getString("transportOrdersContainerPanel.table_orders.popupMenuItem_copyOrder.text"));
    item.setEnabled(singleRowSelected);
    item.addActionListener((ActionEvent evt) -> createCopyOfSelectedTransportOrder());

    menu.show(fTable, x, y);
  }

  private void addControlButtons(JToolBar toolBar) {
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TRANSPORTORDER_PATH);

    toolBar.add(new JToolBar.Separator());

    JButton button = new JButton(
        IconToolkit.instance().getImageIconByFullPath(ICON_PATH + "table-row-delete-2.16x16.png")
    );
    button.addActionListener((ActionEvent e) -> withdrawTransportOrder());
    button.setToolTipText(
        bundle.getString("transportOrdersContainerPanel.button_withdrawSelectedOrders.tooltipText")
    );
    toolBar.add(button);
  }

  private Optional<TransportOrder> getSelectedTransportOrder() {
    int row = fTable.convertRowIndexToModel(fTable.getSelectedRow());
    if (row == -1) {
      return Optional.empty();
    }

    return Optional.of(tableModel.getEntryAt(row));
  }

  private List<JToggleButton> createFilterButtons() {
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.TRANSPORTORDER_PATH);
    JToggleButton button;
    List<JToggleButton> buttons = new ArrayList<>();
    IconToolkit iconkit = IconToolkit.instance();

    button = new FilterButton(iconkit.getImageIconByFullPath(ICON_PATH + "filterRaw.16x16.gif"),
                              createFilterForState(RAW),
                              sorter);

    button.setToolTipText(bundle.getString("transportOrdersContainerPanel.button_filterRawOrders.tooltipText"));
    buttons.add(button);

    button
        = new FilterButton(iconkit.getImageIconByFullPath(ICON_PATH + "filterActivated.16x16.gif"),
                           createFilterForState(DISPATCHABLE),
                           sorter);
    button.setToolTipText(bundle.getString("transportOrdersContainerPanel.button_filterDispatchableOrders.tooltipText"));
    buttons.add(button);

    button
        = new FilterButton(iconkit.getImageIconByFullPath(ICON_PATH + "filterProcessing.16x16.gif"),
                           createFilterForState(BEING_PROCESSED),
                           sorter);
    button.setToolTipText(bundle.getString("transportOrdersContainerPanel.button_filterProcessedOrders.tooltipText"));
    buttons.add(button);

    button
        = new FilterButton(iconkit.getImageIconByFullPath(ICON_PATH + "filterFinished.16x16.gif"),
                           createFilterForState(FINISHED),
                           sorter);
    button.setToolTipText(bundle.getString("transportOrdersContainerPanel.button_filterFinishedOrders.tooltipText"));
    buttons.add(button);

    button = new FilterButton(iconkit.getImageIconByFullPath(ICON_PATH + "filterFailed.16x16.gif"),
                              createFilterForState(FAILED),
                              sorter);
    button.setToolTipText(bundle.getString("transportOrdersContainerPanel.button_filterFailedOrders.tooltipText"));
    buttons.add(button);

    return buttons;
  }

  private RowFilter<Object, Object> createFilterForState(TransportOrder.State state) {
    return new RowFilter<Object, Object>() {
      @Override
      public boolean include(Entry<? extends Object, ? extends Object> entry) {
        TransportOrder order = ((TransportOrderTableModel) entry.getModel()).getEntryAt((int) entry.getIdentifier());
        return order.getState() != state;
      }
    };
  }

  private JToolBar createToolBar(List<JToggleButton> filterButtons) {
    JToolBar toolBar = new JToolBar();

    for (JToggleButton button : filterButtons) {
      toolBar.add(button);
    }

    return toolBar;
  }

  private void withdrawTransportOrder() {
    int[] indices = fTable.getSelectedRows();
    List<TransportOrder> toWithdraw = new ArrayList<>();

    for (int i = 0; i < indices.length; i++) {
      int modelIndex = fTable.convertRowIndexToModel(indices[i]);
      TransportOrder order = tableModel.getEntryAt(modelIndex);
      toWithdraw.add(order);
    }

    try (SharedKernelServicePortal sharedPortal = portalProvider.register()) {
      for (TransportOrder order : toWithdraw) {
        sharedPortal.getPortal().getDispatcherService()
            .withdrawByTransportOrder(order.getReference(), false);
      }
    }
    catch (KernelRuntimeException exc) {
      LOG.warn("Exception withdrawing transport order", exc);
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/candidate/CandidateComparatorIdleFirst.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.candidate;

import java.util.Comparator;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorIdleFirst;

/**
 * Compares {@link AssignmentCandidate}s by vehicles' states, ordering IDLE vehicles first.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorIdleFirst
    implements Comparator<AssignmentCandidate> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "IDLE_FIRST";

  private final Comparator<Vehicle> delegate = new VehicleComparatorIdleFirst();

  /**
   * Compares two candidates by the state of their vehicles.
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param candidate1 The first candiate.
   * @param candidate2 The second candidate.
   * @return The value zero if the vehicles of candidate1 and candidate2 have the same state;
   * a value grater zero, if the vehicle state of candidate1 is idle, unlike candidate2;
   * a value less than zero otherwise.
   */
  @Override
  public int compare(AssignmentCandidate candidate1, AssignmentCandidate candidate2) {
    return delegate.compare(candidate1.getVehicle(), candidate2.getVehicle());
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/vehicles/IsAvailableForAnyOrder.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.vehicles;

import static java.util.Objects.requireNonNull;
import java.util.function.Predicate;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.OrderReservationPool;
import org.opentcs.strategies.basic.dispatching.selection.VehicleSelectionFilter;

/**
 * Filters vehicles that are generally available for transport orders.
 *
 * <p>
 * Note: This filter is not a {@link VehicleSelectionFilter} by intention, since it is not
 * intended to be used in contexts where {@link ObjectHistory} entries are created.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class IsAvailableForAnyOrder
    implements Predicate<Vehicle> {

  /**
   * The object service.
   */
  private final TCSObjectService objectService;
  /**
   * Stores reservations of orders for vehicles.
   */
  private final OrderReservationPool orderReservationPool;
  /**
   * The default dispatcher configuration.
   */
  private final DefaultDispatcherConfiguration configuration;

  /**
   * Creates a new instance.
   *
   * @param objectService The object service.
   * @param orderReservationPool Stores reservations of orders for vehicles.
   * @param configuration The default dispatcher configuration.
   */
  @Inject
  public IsAvailableForAnyOrder(TCSObjectService objectService,
                                OrderReservationPool orderReservationPool,
                                DefaultDispatcherConfiguration configuration) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.orderReservationPool = requireNonNull(orderReservationPool, "orderReservationPool");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public boolean test(Vehicle vehicle) {
    return vehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_UTILIZED
        && vehicle.getCurrentPosition() != null
        && vehicle.getOrderSequence() == null
        && !vehicle.isEnergyLevelCritical()
        && !needsMoreCharging(vehicle)
        && (processesNoOrder(vehicle)
            || processesDispensableOrder(vehicle))
        && !hasOrderReservation(vehicle);
  }

  private boolean needsMoreCharging(Vehicle vehicle) {
    return vehicle.hasState(Vehicle.State.CHARGING)
        && !rechargeThresholdReached(vehicle);
  }

  private boolean rechargeThresholdReached(Vehicle vehicle) {
    return configuration.keepRechargingUntilFullyCharged()
        ? vehicle.isEnergyLevelFullyRecharged()
        : vehicle.isEnergyLevelSufficientlyRecharged();
  }

  private boolean processesNoOrder(Vehicle vehicle) {
    return vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && (vehicle.hasState(Vehicle.State.IDLE)
            || vehicle.hasState(Vehicle.State.CHARGING));
  }

  private boolean processesDispensableOrder(Vehicle vehicle) {
    return vehicle.hasProcState(Vehicle.ProcState.PROCESSING_ORDER)
        && objectService.fetchObject(TransportOrder.class, vehicle.getTransportOrder())
            .isDispensable();
  }

  private boolean hasOrderReservation(Vehicle vehicle) {
    return !orderReservationPool.findReservations(vehicle.getReference()).isEmpty();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/menus/menubar/PluginPanelPropertyHandler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.menus.menubar;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Objects;
import javax.swing.JCheckBoxMenuItem;
import org.opentcs.guing.components.dockable.AbstractDockingManager;

/**
 * Handles changes of a plugin panel's properties.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class PluginPanelPropertyHandler
    implements PropertyChangeListener {

  /**
   * The menu item corresponding to the plugin panel.
   */
  private final JCheckBoxMenuItem utilMenuItem;

  /**
   * Creates a new instance.
   *
   * @param utilMenuItem The menu item corresponding to the plugin panel.
   */
  public PluginPanelPropertyHandler(JCheckBoxMenuItem utilMenuItem) {
    this.utilMenuItem = Objects.requireNonNull(utilMenuItem, "utilMenuItem is null");
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if (evt.getPropertyName().equals(AbstractDockingManager.DOCKABLE_CLOSED)) {
      utilMenuItem.setSelected(false);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteSchedulerServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.SchedulerAllocationState;
import org.opentcs.components.kernel.services.SchedulerService;

/**
 * The default implementation of the scheduler service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemoteSchedulerServiceProxy
    extends AbstractRemoteServiceProxy<RemoteSchedulerService>
    implements SchedulerService {

  @Override
  public SchedulerAllocationState fetchSchedulerAllocations()
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchSchedulerAllocations(getClientId());
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/LocationTheme.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.awt.Image;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.visualization.LocationRepresentation;
import org.opentcs.util.annotations.ScheduledApiChange;

/**
 * Provides a location theme.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public interface LocationTheme {

  /**
   * Returns the image for the given location representation.
   *
   * @param representation The representation for which to return the image.
   * @return The image for the given location representation.
   */
  @Nonnull
  Image getImageFor(@Nonnull LocationRepresentation representation);

  /**
   * Returns the image for the given location (type).
   *
   * @param location The location to base the image on.
   * @param locationType The location type for the location.
   * @return The image for the give location.
   */
  @Nonnull
  @ScheduledApiChange(when = "6.0", details = "Default implementation will be removed.")
  default Image getImageFor(@Nonnull Location location, @Nonnull LocationType locationType) {
    return getImageFor(LocationRepresentation.NONE);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/util/ExplainedBoolean.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;

/**
 * A boolean with an explanation/reason for its value.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ExplainedBoolean {

  /**
   * The actual value.
   */
  private final boolean value;
  /**
   * A reason/explanation for the value.
   */
  private final String reason;

  /**
   * Creates a new instance.
   *
   * @param value The actual value.
   * @param reason A reason/explanation for the value.
   */
  public ExplainedBoolean(boolean value, @Nonnull String reason) {
    this.value = value;
    this.reason = requireNonNull(reason, "reason");
  }

  /**
   * Returns the actual value.
   *
   * @return The actual value.
   */
  public boolean getValue() {
    return value;
  }

  /**
   * A reason/explanation for the value.
   *
   * @return The reason
   */
  @Nonnull
  public String getReason() {
    return reason;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/DefaultPeripheralControllerPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralController;
import static org.opentcs.util.Assertions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Maintains associations of {@link Location}, {@link PeripheralController} and
 * {@link PeripheralCommAdapter}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPeripheralControllerPool
    implements LocalPeripheralControllerPool {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultPeripheralControllerPool.class);
  /**
   * The object service to use.
   */
  private final TCSObjectService objectService;
  /**
   * A factory for peripheral controllers.
   */
  private final PeripheralControllerFactory controllerFactory;
  /**
   * The entries of this pool mapped to the corresponding locations.
   */
  private final Map<TCSResourceReference<Location>, PoolEntry> poolEntries = new HashMap<>();
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new DefaultPeripheralControllerPool.
   *
   * @param objectService The object service to be used.
   * @param controllerFactory The controller factory to be used.
   */
  @Inject
  public DefaultPeripheralControllerPool(TCSObjectService objectService,
                                         PeripheralControllerFactory controllerFactory) {
    this.objectService = requireNonNull(objectService, "objectService");
    this.controllerFactory = requireNonNull(controllerFactory, "controllerFactory");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      LOG.debug("Already initialized, doing nothing.");
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      LOG.debug("Not initialized, doing nothing.");
      return;
    }
    // Detach all peripherals.
    for (PoolEntry curEntry : poolEntries.values()) {
      curEntry.controller.terminate();
    }
    poolEntries.clear();

    initialized = false;
  }

  @Override
  public PeripheralController getPeripheralController(TCSResourceReference<Location> locationRef)
      throws IllegalArgumentException {
    requireNonNull(locationRef, "locationRef");
    checkArgument(poolEntries.containsKey(locationRef),
                  "No controller present for %s",
                  locationRef.getName());

    return poolEntries.get(locationRef).getController();
  }

  @Override
  public void attachPeripheralController(TCSResourceReference<Location> locationRef,
                                         PeripheralCommAdapter commAdapter)
      throws IllegalArgumentException {
    requireNonNull(locationRef, "locationRef");
    requireNonNull(commAdapter, "commAdapter");

    if (poolEntries.containsKey(locationRef)) {
      LOG.warn("{}: Peripheral controller already attached, doing nothing.", locationRef.getName());
      return;
    }

    Location location = objectService.fetchObject(Location.class, locationRef);
    checkArgument(location != null, "No such location: %s", locationRef.getName());

    LOG.debug("{}: Attaching controller...", locationRef.getName());
    PeripheralController controller = controllerFactory.createVehicleController(locationRef,
                                                                                commAdapter);
    poolEntries.put(locationRef, new PoolEntry(locationRef, controller, commAdapter));
    controller.initialize();
  }

  @Override
  public void detachPeripheralController(TCSResourceReference<Location> locationRef) {
    requireNonNull(locationRef, "locationRef");

    if (!poolEntries.containsKey(locationRef)) {
      LOG.warn("{}: No peripheral controller attached, doing nothing.", locationRef.getName());
      return;
    }

    LOG.debug("{}: Detaching controller...", locationRef.getName());
    poolEntries.remove(locationRef).getController().terminate();
  }

  /**
   * An entry in this controller pool.
   */
  private static class PoolEntry {

    /**
     * The location.
     */
    private final TCSResourceReference<Location> location;
    /**
     * The peripheral controller associated with the location.
     */
    private final PeripheralController controller;
    /**
     * The comm adapter associated with the location.
     */
    private final PeripheralCommAdapter commAdapter;

    /**
     * Creates a new pool entry.
     *
     * @param location The location.
     * @param controller The peripheral controller associated with the location.
     * @param cmmmAdapter The comm adapter associated with the location.
     */
    private PoolEntry(TCSResourceReference<Location> location,
                      PeripheralController controller,
                      PeripheralCommAdapter cmmmAdapter) {
      this.location = requireNonNull(location, "location");
      this.controller = requireNonNull(controller, "controller");
      this.commAdapter = requireNonNull(cmmmAdapter, "cmmmAdapter");
    }

    public TCSResourceReference<Location> getLocation() {
      return location;
    }

    public PeripheralController getController() {
      return controller;
    }

    public PeripheralCommAdapter getCommAdapter() {
      return commAdapter;
    }
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

/**
 * This interface provides access to vehicle-property keys that are used in both the
 * plant overview as well as in the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LoopbackAdapterConstants {

  /**
   * The key of the vehicle property that specifies the vehicle's initial position.
   */
  String PROPKEY_INITIAL_POSITION = "loopback:initialPosition";
  /**
   * The key of the vehicle property that specifies the default operating time.
   */
  String PROPKEY_OPERATING_TIME = "loopback:operatingTime";
  /**
   * The key of the vehicle property that specifies which operation loads the load handling device.
   */
  String PROPKEY_LOAD_OPERATION = "loopback:loadOperation";
  /**
   * The default value of the load operation property.
   */
  String PROPVAL_LOAD_OPERATION_DEFAULT = "Load cargo";
  /**
   * The key of the vehicle property that specifies which operation unloads the load handling device.
   */
  String PROPKEY_UNLOAD_OPERATION = "loopback:unloadOperation";
  /**
   * The default value of the unload operation property.
   */
  String PROPVAL_UNLOAD_OPERATION_DEFAULT = "Unload cargo";
  /**
   * The key of the vehicle property that specifies the maximum acceleration of a vehicle.
   */
  String PROPKEY_ACCELERATION = "loopback:acceleration";
  /**
   * The key of the vehicle property that specifies the maximum decceleration of a vehicle.
   */
  String PROPKEY_DECELERATION = "loopback:deceleration";

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/management/PeripheralProcessModelEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals.management;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;

/**
 * Instances of this class represent events emitted by/for changes on
 * {@link PeripheralProcessModel}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralProcessModelEvent
    extends PeripheralCommAdapterEvent
    implements Serializable {

  /**
   * The location assiciated with the peripheral device.
   */
  private final TCSResourceReference<Location> location;
  /**
   * The name of the attribute that has changed in the process model.
   */
  private final String attributeChanged;
  /**
   * The process model with its current/changed state.
   */
  private final PeripheralProcessModel processModel;

  /**
   * Creates a new instance.
   *
   * @param location The location assiciated with the peripheral device.
   * @param attributeChanged The name of the attribute that has changed in the process model.
   * @param processModel The process model with its current/changed state.
   */
  public PeripheralProcessModelEvent(@Nonnull TCSResourceReference<Location> location,
                                     @Nonnull String attributeChanged,
                                     @Nonnull PeripheralProcessModel processModel) {
    this.location = requireNonNull(location, "location");
    this.attributeChanged = requireNonNull(attributeChanged, "attributeChanged");
    this.processModel = requireNonNull(processModel, "processModel");
  }

  /**
   * Returns the location assiciated with the peripheral device.
   *
   * @return The location.
   */
  public TCSResourceReference<Location> getLocation() {
    return location;
  }

  /**
   * Returns the name of the attribute that has changed in the process model.
   *
   * @return The name of the attribute that has changed in the process model.
   */
  public String getAttributeChanged() {
    return attributeChanged;
  }

  /**
   * Returns the process model with its current/changed state.
   *
   * @return The process model with its current/changed state.
   */
  public PeripheralProcessModel getProcessModel() {
    return processModel;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/AssignmentCandidate.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import java.util.List;
import static java.util.Objects.requireNonNull;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * Contains information for a potential assignment of a transport order to a vehicle.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignmentCandidate {

  /**
   * The vehicle.
   */
  private final Vehicle vehicle;
  /**
   * The transport order.
   */
  private final TransportOrder transportOrder;
  /**
   * The route/drive orders to be executed upon assignment.
   */
  private final List<DriveOrder> driveOrders;
  /**
   * The completeRoutingCosts for processing the whole order with the vehicle.
   */
  private final long completeRoutingCosts;

  /**
   * Creates a new instance.
   *
   * @param vehicle The vehicle that would be assigned to the transport order.
   * @param transportOrder The transport order that would be assigned to the vehicle.
   * @param driveOrders The drive orders containing the computed route the vehicle would take. May
   * not be empty.
   */
  public AssignmentCandidate(Vehicle vehicle,
                             TransportOrder transportOrder,
                             List<DriveOrder> driveOrders) {
    this.vehicle = requireNonNull(vehicle, "vehicle");
    this.transportOrder = requireNonNull(transportOrder, "transportOrder");
    this.driveOrders = requireNonNull(driveOrders, "driveOrders");
    checkArgument(!driveOrders.isEmpty(), "driveOrders is empty");
    this.completeRoutingCosts = cumulatedCosts(driveOrders);
  }

  public Vehicle getVehicle() {
    return vehicle;
  }

  public TransportOrder getTransportOrder() {
    return transportOrder;
  }

  public List<DriveOrder> getDriveOrders() {
    return driveOrders;
  }

  /**
   * Returns the costs for travelling only the first drive order/reaching the first destination.
   *
   * @return The costs for travelling only the first drive order.
   */
  public long getInitialRoutingCosts() {
    return driveOrders.get(0).getRoute().getCosts();
  }

  /**
   * Returns the costs for travelling all drive orders.
   *
   * @return The costs for travelling all drive orders.
   */
  public long getCompleteRoutingCosts() {
    return completeRoutingCosts;
  }

  private static long cumulatedCosts(List<DriveOrder> driveOrders) {
    return driveOrders.stream().mapToLong(driveOrder -> driveOrder.getRoute().getCosts()).sum();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/AttributesTable.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.components.properties.event.TableChangeListener;
import org.opentcs.guing.components.properties.event.TableSelectionChangeEvent;
import org.opentcs.guing.components.properties.type.ModelAttribute;

/**
 * A table in which properties are displayed and can be edited.
 * The table has two columns, the first with the name of the property and the second with the 
 * value of the property.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class AttributesTable
    extends JTable {

  /**
   * Stores the application's current state.
   */
  private final ApplicationState appState;
  /**
   * List of table change listeners.
   */
  private final List<TableChangeListener> fTableChangeListeners
      = new LinkedList<>();

  /**
   * Creates a new instance.
   * 
   * @param appState Stores the application's current state.
   */
  @Inject
  public AttributesTable(ApplicationState appState) {
    this.appState = requireNonNull(appState, "appState");
    setStyle();
    putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
  }

  /**
   * Initialises the style of the table.
   */
  protected final void setStyle() {
    setRowHeight(20);
    setCellSelectionEnabled(false);
    getTableHeader().setReorderingAllowed(false);
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    ListSelectionModel model = getSelectionModel();
    model.addListSelectionListener(new ListSelectionListener() {
      @Override
      public void valueChanged(ListSelectionEvent e) {
        if (e.getValueIsAdjusting()) {
          return;
        }

        ListSelectionModel l = (ListSelectionModel) e.getSource();

        if (l.isSelectionEmpty()) {
          fireSelectionChanged(null);
        }
        else {
          int selectedRow = l.getMinSelectionIndex();
          fireSelectionChanged(getModel().getValueAt(selectedRow, 1));
        }
      }
    });
  }

  /**
   * Adds a TableSelectionChangeListener.
   *
   * @param l The listener to add.
   */
  public void addTableChangeListener(TableChangeListener l) {
    fTableChangeListeners.add(l);
  }

  /**
   * Removes a TableSelectionChangeListener.
   *
   * @param l the listener to remove.
   */
  public void removeTableChangeListener(TableChangeListener l) {
    fTableChangeListeners.remove(l);
  }

  /**
   * Notify all registered listeners that a table row has been selected.
   *
   * @param selectedValue
   */
  protected void fireSelectionChanged(Object selectedValue) {
    for (TableChangeListener l : fTableChangeListeners) {
      l.tableSelectionChanged(new TableSelectionChangeEvent(this, selectedValue));
    }
  }

  @Override
  public TableCellEditor getCellEditor(int row, int column) {
    TableModel tableModel = getModel();
    Object value = tableModel.getValueAt(row, column);
    TableCellEditor editor = getDefaultEditor(value.getClass());

    return editor;
  }

  @Override
  public TableCellRenderer getCellRenderer(int row, int column) {
    TableModel tableModel = getModel();
    Object value = tableModel.getValueAt(row, column);
    TableCellRenderer renderer = getDefaultRenderer(value.getClass());

    return renderer;
  }

  /**
   * Indicates whether the specified row is editable.
   *
   * @param row The index of the row to be checked.
   * @return True if the row is editable.
   */
  public boolean isEditable(int row) { 
    AttributesTableModel tableModel = (AttributesTableModel) getModel();
    ModelAttribute attribute = (ModelAttribute) tableModel.getValueAt(row, 1);

    if (appState.hasOperationMode(OperationMode.MODELLING)) {
      return attribute.isModellingEditable();
    }

    return attribute.isOperatingEditable();
  }

  @Override
  public void tableChanged(TableModelEvent event) {
    super.tableChanged(event);

    if (fTableChangeListeners != null) {
      for (TableChangeListener listener : fTableChangeListeners) {
        listener.tableModelChanged();
      }
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/persistence/ModelKernelPersistor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence;

import java.util.HashSet;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.guing.application.StatusPanel;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Persists data kept in {@link SystemModel}s to the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelKernelPersistor {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ModelKernelPersistor.class);
  /**
   * The status panel for logging error messages.
   */
  private final StatusPanel statusPanel;
  /**
   * Provides new instances to validate a system model.
   */
  private final Provider<ModelValidator> validatorProvider;

  private final ModelExportAdapter modelExportAdapter;

  /**
   * Creates a new instance.
   *
   * @param statusPanel A status panel for logging error messages.
   * @param validatorProvider Provides validators for system models.
   * @param modelExportAdapter Converts model data on export.
   */
  @Inject
  public ModelKernelPersistor(@Nonnull StatusPanel statusPanel,
                              @Nonnull Provider<ModelValidator> validatorProvider,
                              ModelExportAdapter modelExportAdapter) {
    this.statusPanel = requireNonNull(statusPanel, "statusPanel");
    this.validatorProvider = requireNonNull(validatorProvider, "validatorProvider");
    this.modelExportAdapter = requireNonNull(modelExportAdapter, "modelExportAdapter");
  }

  /**
   * Persists the given model to the given kernel.
   *
   * @param systemModel The model to be persisted.
   * @param portal The plant model service used to persist to the kernel.
   * @param ignoreValidationErrors Whether to ignore any validation errors.
   * @return {@code true} if, and only if, the model was valid or validation errors were to be
   * ignored.
   * @throws IllegalStateException If there was a problem persisting the model on the kernel side.
   */
  public boolean persist(SystemModel systemModel,
                         KernelServicePortal portal,
                         boolean ignoreValidationErrors)
      throws IllegalStateException {
    requireNonNull(systemModel, "systemModel");
    requireNonNull(portal, "plantModelService");

    LOG.debug("Validating model...");
    long timeBefore = System.currentTimeMillis();
    if (!valid(systemModel) && !ignoreValidationErrors) {
      return false;
    }
    LOG.debug("Validating took {} milliseconds.", System.currentTimeMillis() - timeBefore);

    LOG.debug("Persisting model...");
    timeBefore = System.currentTimeMillis();
    portal.getPlantModelService().createPlantModel(modelExportAdapter.convert(systemModel));
    LOG.debug("Persisting to kernel took {} milliseconds.", System.currentTimeMillis() - timeBefore);

    return true;
  }

  private boolean valid(SystemModel systemModel) {
    ModelValidator validator = validatorProvider.get();
    boolean valid = true;
    for (ModelComponent component : systemModel.getAll()) {
      valid &= validator.isValidWith(systemModel, component);
    }
    //Report possible duplicates if we persist to the kernel
    if (!valid) {
      //Use a hash set to avoid duplicate errors
      Set<String> errors = new HashSet<>(validator.getErrors());
      validator.showSavingValidationWarning(statusPanel, errors);
    }
    return valid;
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/VehicleControllerPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import javax.annotation.Nonnull;

/**
 * Maintains associations between vehicles and vehicle controllers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface VehicleControllerPool {

  /**
   * Returns the vehicle controller associated with the vehicle with the given name.
   * If no vehicle controller is associated with it or if there is no vehicle with the given name,
   * a null-object equivalent will be returned.
   *
   * @param vehicleName The name of the vehicle for which to return the vehicle controller.
   * @return the vehicle controller associated with the vehicle with the given name, or a
   * null-object equivalent.
   */
  @Nonnull
  VehicleController getVehicleController(String vehicleName);
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/event/AttributesChangeEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.event;

import java.util.EventObject;
import org.opentcs.guing.model.ModelComponent;

/**
 * An event that notifies all {@link AttributesChangeListener}s that a model component has been
 * changed.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class AttributesChangeEvent
    extends EventObject {

  /**
   * The model.
   */
  protected ModelComponent fModelComponent;

  /**
   * Creates a new instance.
   *
   * @param listener The listener.
   * @param model The model component.
   */
  public AttributesChangeEvent(AttributesChangeListener listener, ModelComponent model) {
    super(listener);
    fModelComponent = model;
  }

  /**
   * @return the model.
   */
  public ModelComponent getModel() {
    return fModelComponent;
  }

  /**
   * @return the initiator.
   */
  public AttributesChangeListener getInitiator() {
    return (AttributesChangeListener) getSource();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/panel/KeyValueSetPropertyViewerEditorPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.panel;

import com.google.inject.Inject;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
import javax.swing.JPanel;
import javax.swing.table.DefaultTableModel;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.util.I18nPlantOverview;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * UI for viewing a key value property without being able to edit the property.
 *
 * @see KeyValueSetProperty
 * @author <NAME> (Fraunhofer IML)
 */
public class KeyValueSetPropertyViewerEditorPanel
    extends JPanel
    implements DetailsDialogContent {

  /**
   * A resource bundle.
   */
  private final ResourceBundleUtil resBundle
      = ResourceBundleUtil.getBundle(I18nPlantOverview.PROPERTIES_PATH);
  /**
   * The property edited.
   */
  private KeyValueSetProperty fProperty;

  /**
   * Creates a new instance.
   */
  @Inject
  public KeyValueSetPropertyViewerEditorPanel() {
    initComponents();

    itemsTable.setModel(new ItemsTableModel());

    setPreferredSize(new Dimension(350, 200));
  }

  @Override
  public void setProperty(Property property) {
    fProperty = (KeyValueSetProperty) property;

    ItemsTableModel model = (ItemsTableModel) itemsTable.getModel();

    model.setRowCount(0);

    for (KeyValueProperty p : fProperty.getItems()) {
      model.addRow(new String[]{p.getKey(), p.getValue()});
    }

    sortItems();
  }

  @Override
  public void updateValues() {
  }

  @Override
  public String getTitle() {
    return resBundle.getString("keyValueSetPropertyViewerEditorPanel.title");
  }

  @Override
  public KeyValueSetProperty getProperty() {
    return fProperty;
  }

  /**
   * Sorts the entries based on their keys.
   */
  protected void sortItems() {
    Map<String, String> items = new HashMap<>();

    for (int i = 0; i < itemsTable.getRowCount(); i++) {
      items.put((String) itemsTable.getValueAt(i, 0), (String) itemsTable.getValueAt(i, 1));
    }

    int index = 0;

    for (String key : new TreeSet<>(items.keySet())) {
      String value = items.get(key);

      itemsTable.setValueAt(key, index, 0);
      itemsTable.setValueAt(value, index, 1);

      index++;
    }
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    itemsScrollPane = new javax.swing.JScrollPane();
    itemsTable = new javax.swing.JTable();
    controlPanel = new javax.swing.JPanel();

    setLayout(new java.awt.BorderLayout());

    itemsTable.setModel(new javax.swing.table.DefaultTableModel(
      new Object [][] {

      },
      new String [] {

      }
    ));
    itemsScrollPane.setViewportView(itemsTable);

    add(itemsScrollPane, java.awt.BorderLayout.CENTER);

    controlPanel.setLayout(new java.awt.GridBagLayout());
    add(controlPanel, java.awt.BorderLayout.EAST);
  }// </editor-fold>//GEN-END:initComponents

  // CHECKSTYLE:OFF
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel controlPanel;
  private javax.swing.JScrollPane itemsScrollPane;
  private javax.swing.JTable itemsTable;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON

  protected class ItemsTableModel
      extends DefaultTableModel {

    private final Class<?>[] types = new Class<?>[]{
      String.class, String.class
    };

    public ItemsTableModel() {
      super(
          new Object[][]{},
          new String[]{
            resBundle.getString("keyValueSetPropertyViewerEditorPanel.table_properties.column_key.headerText"),
            resBundle.getString("keyValueSetPropertyViewerEditorPanel.table_properties.column_value.headerText")
          }
      );
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
      return types[columnIndex];
    }

    @Override
    public boolean isCellEditable(int row, int column) {
      return false;
    }
  }

}


<|start_filename|>openTCS-Common/src/test/java/org/opentcs/util/persistence/V003DrivingCoursePersistenceTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.junit.*;
import static org.junit.Assert.assertTrue;
import org.opentcs.util.persistence.v003.AllowedOperationTO;
import org.opentcs.util.persistence.v003.BlockTO;
import org.opentcs.util.persistence.v003.GroupTO;
import org.opentcs.util.persistence.v003.LocationTO;
import org.opentcs.util.persistence.v003.LocationTO.Link;
import org.opentcs.util.persistence.v003.LocationTypeTO;
import org.opentcs.util.persistence.v003.MemberTO;
import org.opentcs.util.persistence.v003.PathTO;
import org.opentcs.util.persistence.v003.PointTO;
import org.opentcs.util.persistence.v003.PointTO.OutgoingPath;
import org.opentcs.util.persistence.v003.PropertyTO;
import org.opentcs.util.persistence.v003.V003PlantModelTO;
import org.opentcs.util.persistence.v003.VehicleTO;
import org.opentcs.util.persistence.v003.VisualLayoutTO;
import org.opentcs.util.persistence.v003.VisualLayoutTO.ModelLayoutElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class V003DrivingCoursePersistenceTest {

  private static final Logger LOG = LoggerFactory.getLogger(V003DrivingCoursePersistenceTest.class);

  public V003DrivingCoursePersistenceTest() {
  }

  @Before
  public void setUp() {
  }

  @After
  public void tearDown() {

  }

  @Test
  public void testToXml()
      throws IOException {
    V003PlantModelTO model = new V003PlantModelTO();
    model.setVersion("0.0.3");
    model.setName("Demo");

    PointTO point1 = createPoint("Point1", 1, 2, 3, Float.NaN, "HALT_POSITION",
                                 Arrays.asList(createOutgoingPath("Path1")),
                                 new ArrayList<>());
    PointTO point2 = createPoint("Point2", 4, 5, 6, Float.NaN, "PARK_POSITION",
                                 Arrays.asList(createOutgoingPath("Path2"),
                                               createOutgoingPath("Path3")),
                                 new ArrayList<>());
    model.setPoints(Arrays.asList(point1, point2));

    PathTO path1 = createPath();
    model.setPaths(Arrays.asList(path1));

    VehicleTO vehicle = createVehicle();
    model.setVehicles(Arrays.asList(vehicle));

    LocationTypeTO locType = createLocationType();

    model.setLocationTypes(Arrays.asList(locType));

    LocationTO loc = createLocation();
    model.setLocations(Arrays.asList(loc));

    BlockTO block = createBlock();
    model.setBlocks(Arrays.asList(block));

    GroupTO group = createGroup();
    model.setGroups(Arrays.asList(group));

    VisualLayoutTO vl = createVisualLayout();
    model.setVisualLayouts(Arrays.asList(vl));

    StringWriter writer = new StringWriter();
    model.toXml(writer);

    String xmlOutput = writer.toString();
    LOG.info(xmlOutput);

    try {
      assertTrue(validateXml(new StringReader(xmlOutput)));
    }
    catch (SAXException | IOException ex) {
      LOG.error("", ex);
    }
  }

  private boolean validateXml(Reader reader)
      throws SAXException, IOException {
    Source schemaFile = new StreamSource(getClass().getResourceAsStream(
        "/org/opentcs/util/persistence/model-0.0.3.xsd"));
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = schemaFactory.newSchema(schemaFile);
    try {
      schema.newValidator().validate(new StreamSource(reader));
      LOG.info("XML is valid.");
      return true;
    }
    catch (SAXException e) {
      LOG.info("XML is NOT valid.", e);
      return false;
    }
  }

  private PointTO createPoint(String name, long xPosition, long yPosition, long zPosition,
                              Float vehicleOrientationAngle, String type,
                              List<OutgoingPath> outgoingPaths,
                              List<PropertyTO> properties) {
    PointTO p = new PointTO();
    p.setName(name);
    p.setxPosition(xPosition);
    p.setyPosition(yPosition);
    p.setzPosition(zPosition);
    p.setVehicleOrientationAngle(vehicleOrientationAngle);
    p.setType(type);
    p.setOutgoingPaths(outgoingPaths);
    p.setProperties(properties);
    return p;
  }

  private OutgoingPath createOutgoingPath(String name) {
    OutgoingPath op = new OutgoingPath();
    op.setName(name);
    return op;
  }

  private PathTO createPath() {
    PathTO p = new PathTO();
    p.setName("Point1 --- Point2");
    p.setSourcePoint("Point1");
    p.setDestinationPoint("Point2");
    p.setLength(100L);
    p.setMaxVelocity(1000L);
    p.setMaxReverseVelocity(200L);
    p.setLocked(false);

    PropertyTO property = new PropertyTO();
    property.setName("Property1");
    property.setValue("Value1");
    p.setProperties(Arrays.asList(property));
    return p;
  }

  private LocationTypeTO createLocationType() {
    LocationTypeTO locType = new LocationTypeTO();

    locType.setName("Transfer station");

    AllowedOperationTO ao1 = new AllowedOperationTO();
    ao1.setName("NOP");
    AllowedOperationTO ao2 = new AllowedOperationTO();
    ao2.setName("Load cargo");
    locType.setAllowedOperations(Arrays.asList(ao1, ao2));

    PropertyTO property = new PropertyTO();
    property.setName("tcs:defaultLocationSymbol");
    property.setValue("LOAD_TRANSFER_GENERIC");
    locType.setProperties(Arrays.asList(property));
    return locType;
  }

  private LocationTO createLocation() {
    LocationTO loc = new LocationTO();

    loc.setName("Storage 02");
    loc.setxPosition(100L);
    loc.setyPosition(200L);
    loc.setzPosition(300L);
    loc.setType("Transfer station");

    Link link = new Link();
    link.setPoint("Point1");
    loc.setLinks(Arrays.asList(link));

    return loc;
  }

  private BlockTO createBlock() {
    BlockTO block = new BlockTO();
    block.setName("Block-001");

    MemberTO member = new MemberTO();
    member.setName("Point1 --- Point2");
    block.setMembers(Arrays.asList(member));

    return block;
  }

  private VisualLayoutTO createVisualLayout() {
    VisualLayoutTO vl = new VisualLayoutTO();
    vl.setName("VLayout-01");
    vl.setScaleX(50.0f);
    vl.setScaleY(50.0f);

    ModelLayoutElement mle = new ModelLayoutElement();
    mle.setVisualizedObjectName("Block-0002");
    mle.setLayer(0L);
    PropertyTO property = new PropertyTO();
    property.setName("COLOR");
    property.setValue("#FF0000");
    mle.setProperties(Arrays.asList(property));
    vl.setModelLayoutElements(Arrays.asList(mle));

    property = new PropertyTO();
    property.setName("tcs:vehicleThemeClass");
    property.setValue("...");
    vl.setProperties(Arrays.asList(property));

    return vl;
  }

  private VehicleTO createVehicle() {
    VehicleTO vehicle = new VehicleTO();
    vehicle.setName("Vehicle-01");
    vehicle.setLength(1000L);
    vehicle.setEnergyLevelCritical(30L);
    vehicle.setEnergyLevelGood(90L);
    return vehicle;
  }

  private GroupTO createGroup() {
    GroupTO group = new GroupTO();
    group.setName("Group1");
    MemberTO member = new MemberTO();
    member.setName("Member1");
    group.setMembers(Arrays.asList(member));
    return group;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/AssignReservedOrdersPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase;

import static java.util.Objects.requireNonNull;
import java.util.Optional;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.OrderReservationPool;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;

/**
 * Assigns reserved transport orders (if any) to vehicles that have just finished their withdrawn
 * ones.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssignReservedOrdersPhase
    implements Phase {

  /**
   * The object service
   */
  private final TCSObjectService objectService;
  /**
   * The Router instance calculating route costs.
   */
  private final Router router;
  /**
   * A collection of predicates for filtering assignment candidates.
   */
  private final CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter;
  /**
   * Stores reservations of orders for vehicles.
   */
  private final OrderReservationPool orderReservationPool;

  private final TransportOrderUtil transportOrderUtil;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public AssignReservedOrdersPhase(
      TCSObjectService objectService,
      Router router,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      OrderReservationPool orderReservationPool,
      TransportOrderUtil transportOrderUtil) {
    this.router = requireNonNull(router, "router");
    this.objectService = requireNonNull(objectService, "objectService");
    this.assignmentCandidateSelectionFilter = requireNonNull(assignmentCandidateSelectionFilter,
                                                             "assignmentCandidateSelectionFilter");
    this.orderReservationPool = requireNonNull(orderReservationPool, "orderReservationPool");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }
    initialized = false;
  }

  @Override
  public void run() {
    for (Vehicle vehicle : objectService.fetchObjects(Vehicle.class, this::available)) {
      checkForReservedOrder(vehicle);
    }
  }

  private void checkForReservedOrder(Vehicle vehicle) {
    // Check if there's an order reserved for this vehicle that is in an assignable state. If yes,
    // try to assign that.
    // Note that we expect no more than a single reserved order, and remove ALL reservations if we
    // find at least one, even if it cannot be processed by the vehicle in the end.
    orderReservationPool.findReservations(vehicle.getReference()).stream()
        .map(orderRef -> objectService.fetchObject(TransportOrder.class, orderRef))
        .filter(order -> order.hasState(TransportOrder.State.DISPATCHABLE))
        .limit(1)
        .peek(order -> orderReservationPool.removeReservations(vehicle.getReference()))
        .map(order -> computeCandidate(vehicle,
                                       objectService.fetchObject(Point.class,
                                                                 vehicle.getCurrentPosition()),
                                       order))
        .filter(optCandidate -> optCandidate.isPresent())
        .map(optCandidate -> optCandidate.get())
        .filter(candidate -> assignmentCandidateSelectionFilter.apply(candidate).isEmpty())
        .findFirst()
        .ifPresent(
            candidate -> transportOrderUtil.assignTransportOrder(vehicle,
                                                                 candidate.getTransportOrder(),
                                                                 candidate.getDriveOrders())
        );
  }

  private boolean available(Vehicle vehicle) {
    return vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && (vehicle.hasState(Vehicle.State.IDLE)
            || vehicle.hasState(Vehicle.State.CHARGING));
  }

  private Optional<AssignmentCandidate> computeCandidate(Vehicle vehicle,
                                                         Point vehiclePosition,
                                                         TransportOrder order) {
    return router.getRoute(vehicle, vehiclePosition, order)
        .map(driveOrders -> new AssignmentCandidate(vehicle, order, driveOrders));
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/toolbar/CreationToolFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.toolbar;

import org.jhotdraw.draw.ConnectionFigure;
import org.jhotdraw.draw.Figure;
import org.opentcs.thirdparty.jhotdraw.application.toolbar.OpenTCSConnectionTool;

/**
 * A factory for tools concerned with the creation of figures/model elements.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface CreationToolFactory {

  OpenTCSCreationTool createCreationTool(Figure prototype);

  OpenTCSConnectionTool createConnectionTool(ConnectionFigure prototype);
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/KernelRemoteService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.util.concurrent.ExecutionException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.Lifecycle;

/**
 * A base class for kernel-side implementations of remote services.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class KernelRemoteService
    implements Lifecycle {

  /**
   * The message to log when a service method execution failed.
   */
  private static final String EXECUTION_FAILED_MESSAGE = "Failed to execute service method";

  /**
   * Wraps the given exception into a suitable {@link RuntimeException}.
   *
   * @param exc The exception to find a runtime exception for.
   * @return The runtime exception.
   */
  protected RuntimeException findSuitableExceptionFor(Exception exc) {
    if (exc instanceof InterruptedException) {
      return new IllegalStateException("Unexpectedly interrupted");
    }
    if (exc instanceof ExecutionException
        && exc.getCause() instanceof RuntimeException) {
      return (RuntimeException) exc.getCause();
    }
    return new KernelRuntimeException(EXECUTION_FAILED_MESSAGE, exc.getCause());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/vehicle/SimVehicleCommAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.vehicle;

import javax.annotation.Nullable;

/**
 * This interface declares methods that a vehicle driver intended for simulation
 * must implement.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface SimVehicleCommAdapter
    extends VehicleCommAdapter {

  /**
   * Sets an initial vehicle position.
   * This method should not be called while the communication adapter is
   * simulating order execution for the attached vehicle; the resulting
   * behaviour is undefined.
   *
   * @param newPos The new position.
   */
  void initVehiclePosition(@Nullable String newPos);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/event/TableChangeListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.event;

/** 
 * A listener that listens for changes on a table.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface TableChangeListener
    extends java.util.EventListener {

  /**
   * Indicates that a line in the table has been selected.
   *
   * @param event The event.
   */
  void tableSelectionChanged(TableSelectionChangeEvent event);

  /**
   * Indicates that changes in the table have occured.
   */
  void tableModelChanged();
}


<|start_filename|>openTCS-API-Base/src/test/java/org/opentcs/data/model/ModelSerializationTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;

/**
 * Tests for proper serialization and deserialization of classes derived by TCSObject
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelSerializationTest {

  public ModelSerializationTest() {
  }

  @Test
  public void shouldSerializeAndDeserializeBlock()
      throws Exception {
    Block originalObject = new Block("Block1");
    Block deserializedObject = (Block) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  @Test
  @SuppressWarnings("deprecation")
  public void shouldSerializeAndDeserializeGroup()
      throws Exception {
    Group originalObject = new Group("Group1");
    Group deserializedObject = (Group) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  @Test
  public void shouldSerializeAndDeserializeLocation()
      throws Exception {
    @SuppressWarnings("unchecked")
    Location originalObject = new Location("Location1", mock(TCSObjectReference.class));
    Location deserializedObject = (Location) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  @Test
  public void shouldSerializeAndDeserializeLocationType()
      throws Exception {
    LocationType originalObject = new LocationType("LocationType1");
    LocationType deserializedObject = (LocationType) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  @Test
  public void shouldSerializeAndDeserializePath()
      throws Exception {
    @SuppressWarnings("unchecked")
    Path originalObject = new Path("Path1", mock(TCSObjectReference.class), mock(TCSObjectReference.class));
    Path deserializedObject = (Path) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  @Test
  public void shouldSerializeAndDeserializePoint()
      throws Exception {
    Point originalObject = new Point("Point1");
    Point deserializedObject = (Point) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  @Test
  public void shouldSerializeAndDeserializeVehicle()
      throws Exception {
    Vehicle originalObject = new Vehicle("Vehicle1");
    Vehicle deserializedObject = (Vehicle) deserializeTCSObject(serializeTCSObject(originalObject));

    assertEquals(originalObject, deserializedObject);
  }

  private byte[] serializeTCSObject(TCSObject<?> tcsObject)
      throws IOException {
    byte[] serializedObject;
    try (ByteArrayOutputStream os = new ByteArrayOutputStream();
         ObjectOutputStream oos = new ObjectOutputStream(os)) {
      oos.writeObject(tcsObject);
      serializedObject = os.toByteArray();
    }
    return serializedObject;
  }

  private TCSObject<?> deserializeTCSObject(byte[] serializedObject)
      throws IOException, ClassNotFoundException {
    TCSObject<?> deserializedObject;
    try (ByteArrayInputStream is = new ByteArrayInputStream(serializedObject);
         ObjectInputStream ois = new ObjectInputStream(is)) {
      deserializedObject = (TCSObject) ois.readObject();
    }
    return deserializedObject;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/package-info.java<|end_filename|>
/**
 * The openTCS kernel, its interface for client applications and closely related
 * functionality.
 */
package org.opentcs.kernel;


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/event/NullAttributesChangeListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.event;

/**
 * A PropertiesModelChangeListener that does nothing.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class NullAttributesChangeListener
    implements AttributesChangeListener {

  /**
   * Creates a new instance of NullPropertiesModelChangeListener
   */
  public NullAttributesChangeListener() {
  }

  @Override
  public void propertiesChanged(AttributesChangeEvent e) {
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/ServiceWebApiConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.servicewebapi;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Configuration entries for the service web API.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(ServiceWebApiConfiguration.PREFIX)
public interface ServiceWebApiConfiguration {

  String PREFIX = "servicewebapi";

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to enable the interface.",
      orderKey = "0")
  boolean enable();

  @ConfigurationEntry(
      type = "IP address",
      description = "Address to which to bind the HTTP server, e.g. 0.0.0.0 or 127.0.0.1.",
      orderKey = "1")
  String bindAddress();

  @ConfigurationEntry(
      type = "Integer",
      description = "Port to which to bind the HTTP server.",
      orderKey = "2")
  int bindPort();

  @ConfigurationEntry(
      type = "String",
      description = "Key allowing access to the API.",
      orderKey = "3")
  String accessKey();

  @ConfigurationEntry(
      type = "Integer",
      description = "Maximum number of status events to be kept.",
      orderKey = "4")
  int statusEventsCapacity();

  @ConfigurationEntry(
      type = "Boolean",
      description = "Whether to use SSL to encrypt connections.",
      orderKey = "5")
  boolean useSsl();
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/LocationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "xPosition", "yPosition", "zPosition", "links", "locked",
                      "properties"})
public class LocationTO
    extends PlantModelElementTO {

  private Long xPosition = 0L;
  private Long yPosition = 0L;
  private Long zPosition = 0L;
  private String type = "";
  private List<Link> links = new ArrayList<>();
  private Boolean locked = false;

  @XmlAttribute
  public Long getxPosition() {
    return xPosition;
  }

  public LocationTO setxPosition(@Nonnull Long xPosition) {
    requireNonNull(xPosition, "xPosition");
    this.xPosition = xPosition;
    return this;
  }

  @XmlAttribute
  public Long getyPosition() {
    return yPosition;
  }

  public LocationTO setyPosition(@Nonnull Long yPosition) {
    requireNonNull(yPosition, "yPosition");
    this.yPosition = yPosition;
    return this;
  }

  @XmlAttribute
  public Long getzPosition() {
    return zPosition;
  }

  public LocationTO setzPosition(@Nonnull Long zPosition) {
    requireNonNull(zPosition, "zPosition");
    this.zPosition = zPosition;
    return this;
  }

  @XmlAttribute
  public String getType() {
    return type;
  }

  public LocationTO setType(@Nonnull String type) {
    requireNonNull(type, "type");
    this.type = type;
    return this;
  }

  @XmlElement(name = "link", required = true)
  public List<Link> getLinks() {
    return links;
  }

  public LocationTO setLinks(@Nonnull List<Link> links) {
    requireNonNull(links, "links");
    this.links = links;
    return this;
  }

  @XmlAttribute
  public Boolean isLocked() {
    return locked;
  }

  public LocationTO setLocked(Boolean locked) {
    this.locked = locked;
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"point", "allowedOperations"})
  public static class Link {

    private String point = "";
    private List<AllowedOperationTO> allowedOperations = new ArrayList<>();

    @XmlAttribute(required = true)
    public String getPoint() {
      return point;
    }

    public Link setPoint(@Nonnull String point) {
      requireNonNull(point, "point");
      this.point = point;
      return this;
    }

    @XmlElement(name = "allowedOperation")
    public List<AllowedOperationTO> getAllowedOperations() {
      return allowedOperations;
    }

    public Link setAllowedOperations(@Nonnull List<AllowedOperationTO> allowedOperations) {
      requireNonNull(allowedOperations, "allowedOperations");
      this.allowedOperations = allowedOperations;
      return this;
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/workingset/Model.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.workingset;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.access.to.model.BlockCreationTO;
import org.opentcs.access.to.model.LocationCreationTO;
import org.opentcs.access.to.model.LocationTypeCreationTO;
import org.opentcs.access.to.model.PathCreationTO;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.model.PointCreationTO;
import org.opentcs.access.to.model.VehicleCreationTO;
import org.opentcs.access.to.model.VisualLayoutCreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.data.ObjectExistsException;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Block;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.model.visualization.ElementPropKeys;
import org.opentcs.data.model.visualization.VisualLayout;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.data.peripherals.PeripheralOperation;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;
import static org.opentcs.util.Assertions.checkState;
import org.opentcs.util.Colors;
import org.opentcs.util.annotations.ScheduledApiChange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Instances of this class present a view on the complete static topology of an
 * openTCS model, i.e. Points, Paths etc., and Vehicles, contained
 * in a {@link TCSObjectPool TCSObjectPool}.
 * <p>
 * Note that no synchronization is done inside this class. Concurrent access of
 * instances of this class must be synchronized externally.
 * </p>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Model {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(Model.class);
  /**
   * The system's global object pool.
   */
  private final TCSObjectPool objectPool;
  /**
   * This model's name.
   */
  private String name = "";
  /**
   * This model's properties.
   */
  private Map<String, String> properties = new HashMap<>();

  /**
   * Creates a new model.
   *
   * @param globalPool The object pool serving as the container for this model's
   * data.
   */
  @Inject
  public Model(TCSObjectPool globalPool) {
    this.objectPool = Objects.requireNonNull(globalPool);
  }

  /**
   * Returns the <code>TCSObjectPool</code> serving as the container for this
   * model's data.
   *
   * @return The <code>TCSObjectPool</code> serving as the container for this
   * model's data.
   */
  public TCSObjectPool getObjectPool() {
    LOG.debug("method entry");
    return objectPool;
  }

  /**
   * Returns this model's name.
   *
   * @return This model's name.
   */
  public String getName() {
    LOG.debug("method entry");
    return name;
  }

  /**
   * Sets this model's name.
   *
   * @param name This model's new name.
   */
  public void setName(String name) {
    this.name = requireNonNull(name, "name");
  }

  /**
   * Returns this model's properties.
   *
   * @return This model's properties.
   */
  public Map<String, String> getProperties() {
    return properties;
  }

  /**
   * Sets this model's properties.
   *
   * @param properties The properties.
   */
  public void setProperties(Map<String, String> properties) {
    this.properties = requireNonNull(properties, "properties");
  }

  /**
   * Removes all model objects from this model and the object pool by which it is backed.
   */
  @SuppressWarnings("deprecation")
  public void clear() {
    LOG.debug("method entry");
    for (TCSObject<?> curObject : objectPool.getObjects((Pattern) null)) {
      if (curObject instanceof Point
          || curObject instanceof Path
          || curObject instanceof Vehicle
          || curObject instanceof LocationType
          || curObject instanceof Location
          || curObject instanceof Block
          || curObject instanceof org.opentcs.data.model.Group
          || curObject instanceof VisualLayout) {
        objectPool.removeObject(curObject.getReference());
        objectPool.emitObjectEvent(null,
                                   curObject,
                                   TCSObjectEvent.Type.OBJECT_REMOVED);
      }
    }
  }

  /**
   * Creates new plant model objects with unique IDs and all other attributes taken from the given
   * transfer object.
   *
   * @param to The transfer object from which to create the new objects.
   * @throws ObjectExistsException If an object with a new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  @SuppressWarnings("deprecation")
  public void createPlantModelObjects(PlantModelCreationTO to)
      throws ObjectExistsException, ObjectUnknownException {
    clear();
    setName(to.getName());
    setProperties(to.getProperties());

    for (PointCreationTO point : to.getPoints()) {
      createPoint(point);
    }
    for (LocationTypeCreationTO locType : to.getLocationTypes()) {
      createLocationType(locType);
    }
    for (LocationCreationTO loc : to.getLocations()) {
      createLocation(loc);
    }
    for (PathCreationTO path : to.getPaths()) {
      createPath(path);
    }

    for (BlockCreationTO block : to.getBlocks()) {
      createBlock(block);
    }
    for (org.opentcs.access.to.model.GroupCreationTO group : to.getGroups()) {
      createGroup(group);
    }
    for (VehicleCreationTO vehicle : to.getVehicles()) {
      createVehicle(vehicle);
    }

    createVisualLayout(to.getVisualLayout());
    overrideLayoutData(to.getVisualLayout());
  }

  /**
   * Creates a new visual layout with a unique name and all other attributes set
   * to default values.
   *
   * @param to The transfer object from which to create the new layout.
   * @return The newly created layout.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  public VisualLayout createVisualLayout(VisualLayoutCreationTO to)
      throws ObjectUnknownException, ObjectExistsException {
    VisualLayout newLayout = new VisualLayout(to.getName())
        .withScaleX(to.getScaleX())
        .withScaleY(to.getScaleY())
        .withLayers(to.getLayers())
        .withLayerGroups(to.getLayerGroups());

    objectPool.addObject(newLayout);
    objectPool.emitObjectEvent(newLayout,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);
    // Return the newly created layout.
    return newLayout;
  }

  /**
   * Creates a new point with a unique name and all other attributes set to
   * default values.
   *
   * @param to The transfer object from which to create the new point.
   * @return The newly created point.
   * @throws ObjectExistsException If an object with the point's name already exists.
   */
  public Point createPoint(PointCreationTO to)
      throws ObjectExistsException {
    // Get a unique ID for the new point and create an instance.
    Point newPoint = new Point(to.getName())
        .withPosition(to.getPosition())
        .withType(to.getType())
        .withVehicleOrientationAngle(to.getVehicleOrientationAngle())
        .withProperties(to.getProperties())
        .withLayout(new Point.Layout(to.getLayout().getPosition(),
                                     to.getLayout().getLabelOffset(),
                                     to.getLayout().getLayerId()));
    objectPool.addObject(newPoint);
    objectPool.emitObjectEvent(newPoint, null, TCSObjectEvent.Type.OBJECT_CREATED);
    // Return the newly created point.
    return newPoint;
  }

  /**
   * Creates a new path from the given transfer object.
   *
   * @param to The transfer object from which to create the new path.
   * @return The newly created path.
   * @throws ObjectUnknownException If the referenced point does not exist.
   * @throws ObjectExistsException If an object with the same name as the path already exists.
   */
  public Path createPath(PathCreationTO to)
      throws ObjectUnknownException, ObjectExistsException {
    requireNonNull(to, "to");

    Point srcPoint = objectPool.getObject(Point.class, to.getSrcPointName());
    Point destPoint = objectPool.getObject(Point.class, to.getDestPointName());
    Path newPath = new Path(to.getName(),
                            srcPoint.getReference(),
                            destPoint.getReference())
        .withLength(to.getLength())
        .withMaxVelocity(to.getMaxVelocity())
        .withMaxReverseVelocity(to.getMaxReverseVelocity())
        .withPeripheralOperations(mapPeripheralOperationTOs(to.getPeripheralOperations()))
        .withProperties(to.getProperties())
        .withLocked(to.isLocked())
        .withLayout(new Path.Layout(to.getLayout().getConnectionType(),
                                    to.getLayout().getControlPoints(),
                                    to.getLayout().getLayerId()));

    // Store the instance in the global object pool.
    objectPool.addObject(newPath);

    objectPool.emitObjectEvent(newPath,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);

    addPointOutgoingPath(srcPoint.getReference(), newPath.getReference());
    addPointIncomingPath(destPoint.getReference(), newPath.getReference());

    return newPath;
  }

  /**
   * Locks/Unlocks a path.
   *
   * @param ref A reference to the path to be modified.
   * @param newLocked If <code>true</code>, this path will be locked when the
   * method call returns; if <code>false</code>, this path will be unlocked.
   * @return The modified path.
   * @throws ObjectUnknownException If the referenced path does not exist.
   */
  public Path setPathLocked(TCSObjectReference<Path> ref, boolean newLocked)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Path path = objectPool.getObject(Path.class, ref);
    Path previousState = path;
    path = objectPool.replaceObject(path.withLocked(newLocked));
    objectPool.emitObjectEvent(path,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return path;
  }

  /**
   * Creates a new location type with a unique name and all other attributes set
   * to their default values.
   *
   * @param to The transfer object from which to create the new location type.
   * @return The newly created location type.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   */
  public LocationType createLocationType(LocationTypeCreationTO to)
      throws ObjectExistsException {
    LocationType newType = new LocationType(to.getName())
        .withAllowedOperations(to.getAllowedOperations())
        .withAllowedPeripheralOperations(to.getAllowedPeripheralOperations())
        .withProperties(to.getProperties())
        .withLayout(new LocationType.Layout(to.getLayout().getLocationRepresentation()));
    objectPool.addObject(newType);
    objectPool.emitObjectEvent(newType,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);
    return newType;
  }

  /**
   * Creates a new location with a unique name and all other attributes set to
   * default values.
   *
   * @param to The transfer object from which to create the new location type.
   * @return The newly created location.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  public Location createLocation(LocationCreationTO to)
      throws ObjectUnknownException, ObjectExistsException {
    LocationType type = objectPool.getObject(LocationType.class, to.getTypeName());
    Location newLocation = new Location(to.getName(), type.getReference())
        .withPosition(to.getPosition())
        .withLocked(to.isLocked())
        .withProperties(to.getProperties())
        .withLayout(new Location.Layout(to.getLayout().getPosition(),
                                        to.getLayout().getLabelOffset(),
                                        to.getLayout().getLocationRepresentation(),
                                        to.getLayout().getLayerId()));

    Set<Location.Link> locationLinks = new HashSet<>();
    for (Map.Entry<String, Set<String>> linkEntry : to.getLinks().entrySet()) {
      Point point = objectPool.getObject(Point.class, linkEntry.getKey());
      Location.Link link = new Location.Link(newLocation.getReference(), point.getReference())
          .withAllowedOperations(linkEntry.getValue());
      locationLinks.add(link);
    }
    newLocation = newLocation.withAttachedLinks(locationLinks);

    objectPool.addObject(newLocation);
    objectPool.emitObjectEvent(newLocation,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);

    // Add the location's links to the respective points, too.
    for (Location.Link link : locationLinks) {
      Point point = objectPool.getObjectOrNull(Point.class, link.getPoint());

      Set<Location.Link> pointLinks = new HashSet<>(point.getAttachedLinks());
      pointLinks.add(link);

      Point previousPointState = point;
      point = objectPool.replaceObject(point.withAttachedLinks(pointLinks));

      objectPool.emitObjectEvent(point,
                                 previousPointState,
                                 TCSObjectEvent.Type.OBJECT_MODIFIED);
    }

    return newLocation;
  }

  /**
   * Locks/Unlocks a location.
   *
   * @param ref A reference to the location to be modified.
   * @param newLocked If {@code true}, this path will be locked when the method call returns;
   * if {@code false}, this path will be unlocked.
   * @return The modified location.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  public Location setLocationLocked(TCSObjectReference<Location> ref, boolean newLocked)
      throws ObjectUnknownException {
    Location location = objectPool.getObject(Location.class, ref);
    Location previousState = location;
    location = objectPool.replaceObject(location.withLocked(newLocked));
    objectPool.emitObjectEvent(location,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return location;
  }

  /**
   * Sets a location's reservation token.
   *
   * @param ref A reference to the location to be modified.
   * @param newToken The new reservation token.
   * @return The modified location.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  public Location setLocationReservationToken(TCSObjectReference<Location> ref, String newToken)
      throws ObjectUnknownException {
    Location location = objectPool.getObject(Location.class, ref);
    Location previousState = location;
    location = objectPool.replaceObject(location.withPeripheralInformation(
        location.getPeripheralInformation().withReservationToken(newToken)
    ));
    objectPool.emitObjectEvent(location,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return location;
  }

  /**
   * Sets a location's processing state.
   *
   * @param ref A reference to the location to be modified.
   * @param newState The new processing state.
   * @return The modified location.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  public Location setLocationProcState(TCSObjectReference<Location> ref,
                                       PeripheralInformation.ProcState newState)
      throws ObjectUnknownException {
    Location location = objectPool.getObject(Location.class, ref);
    Location previousState = location;
    location = objectPool.replaceObject(location.withPeripheralInformation(
        location.getPeripheralInformation().withProcState(newState)
    ));
    objectPool.emitObjectEvent(location,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return location;
  }

  /**
   * Sets a location's state.
   *
   * @param ref A reference to the location to be modified.
   * @param newState The new state.
   * @return The modified location.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  public Location setLocationState(TCSObjectReference<Location> ref,
                                   PeripheralInformation.State newState)
      throws ObjectUnknownException {
    Location location = objectPool.getObject(Location.class, ref);
    Location previousState = location;
    location = objectPool.replaceObject(location.withPeripheralInformation(
        location.getPeripheralInformation().withState(newState)
    ));
    objectPool.emitObjectEvent(location,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return location;
  }

  /**
   * Sets a location's peripheral job.
   *
   * @param ref A reference to the location to be modified.
   * @param newJob The new peripheral job.
   * @return The modified location.
   * @throws ObjectUnknownException If the referenced location does not exist.
   */
  public Location setLocationPeripheralJob(TCSObjectReference<Location> ref,
                                           TCSObjectReference<PeripheralJob> newJob)
      throws ObjectUnknownException {
    Location location = objectPool.getObject(Location.class, ref);
    Location previousState = location;
    location = objectPool.replaceObject(location.withPeripheralInformation(
        location.getPeripheralInformation().withPeripheralJob(newJob)
    ));
    objectPool.emitObjectEvent(location,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return location;
  }

  /**
   * Creates a new vehicle with a unique name and all other attributes set to
   * their default values.
   *
   * @param to The transfer object from which to create the new group.
   * @return The newly created group.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   */
  public Vehicle createVehicle(VehicleCreationTO to)
      throws ObjectExistsException {
    Vehicle newVehicle = new Vehicle(to.getName())
        .withLength(to.getLength())
        .withEnergyLevelGood(to.getEnergyLevelGood())
        .withEnergyLevelCritical(to.getEnergyLevelCritical())
        .withEnergyLevelFullyRecharged(to.getEnergyLevelFullyRecharged())
        .withEnergyLevelSufficientlyRecharged(to.getEnergyLevelSufficientlyRecharged())
        .withMaxVelocity(to.getMaxVelocity())
        .withMaxReverseVelocity(to.getMaxReverseVelocity())
        .withProperties(to.getProperties())
        .withLayout(new Vehicle.Layout(to.getLayout().getRouteColor()));
    objectPool.addObject(newVehicle);
    objectPool.emitObjectEvent(newVehicle,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);
    return newVehicle;
  }

  /**
   * Sets a vehicle's energy level.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param energyLevel The vehicle's new energy level.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleEnergyLevel(TCSObjectReference<Vehicle> ref,
                                       int energyLevel)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObjectOrNull(Vehicle.class, ref);
    if (vehicle == null) {
      throw new ObjectUnknownException(ref);
    }
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withEnergyLevel(energyLevel));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's recharge operation.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param rechargeOperation The vehicle's new recharge operation.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleRechargeOperation(TCSObjectReference<Vehicle> ref,
                                             String rechargeOperation)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withRechargeOperation(rechargeOperation));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's load handling devices.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param devices The vehicle's new load handling devices.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleLoadHandlingDevices(TCSObjectReference<Vehicle> ref,
                                               List<LoadHandlingDevice> devices)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withLoadHandlingDevices(devices));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's state.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param newState The vehicle's new state.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleState(TCSObjectReference<Vehicle> ref,
                                 Vehicle.State newState)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withState(newState));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle integration level.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param integrationLevel The vehicle's new integration level.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleIntegrationLevel(TCSObjectReference<Vehicle> ref,
                                            Vehicle.IntegrationLevel integrationLevel)
      throws ObjectUnknownException {
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withIntegrationLevel(integrationLevel));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's processing state.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param newState The vehicle's new processing state.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleProcState(TCSObjectReference<Vehicle> ref,
                                     Vehicle.ProcState newState)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withProcState(newState));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets the allowed order types for a given vehicle.
   *
   * @param ref Reference to the vehicle.
   * @param allowedOrderTypes Set of allowed order types.
   * @return The vehicle with the allowed order types.
   * @throws ObjectUnknownException The vehicle reference is not known.
   */
  public Vehicle setVehicleAllowedOrderTypes(TCSObjectReference<Vehicle> ref,
                                             Set<String> allowedOrderTypes)
      throws ObjectUnknownException {
    Vehicle vehicle = objectPool.getObjectOrNull(Vehicle.class, ref);
    if (vehicle == null) {
      throw new ObjectUnknownException(ref);
    }
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withAllowedOrderTypes(allowedOrderTypes));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's position.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param newPosRef A reference to the point the vehicle is occupying.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehiclePosition(TCSObjectReference<Vehicle> ref,
                                    TCSObjectReference<Point> newPosRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousVehicleState = vehicle;
    // If the vehicle was occupying a point before, clear it and send an event.
    if (vehicle.getCurrentPosition() != null) {
      Point oldVehiclePos = objectPool.getObject(Point.class, vehicle.getCurrentPosition());
      Point previousPointState = oldVehiclePos;
      oldVehiclePos = objectPool.replaceObject(oldVehiclePos.withOccupyingVehicle(null));
      objectPool.emitObjectEvent(oldVehiclePos,
                                 previousPointState,
                                 TCSObjectEvent.Type.OBJECT_MODIFIED);
    }
    // If the vehicle is occupying a point now, set that and send an event.
    if (newPosRef != null) {
      Point newVehiclePos = objectPool.getObject(Point.class, newPosRef);
      Point previousPointState = newVehiclePos;
      newVehiclePos = objectPool.replaceObject(newVehiclePos.withOccupyingVehicle(ref));
      objectPool.emitObjectEvent(newVehiclePos,
                                 previousPointState,
                                 TCSObjectEvent.Type.OBJECT_MODIFIED);
    }
    vehicle = objectPool.replaceObject(vehicle.withCurrentPosition(newPosRef));
    objectPool.emitObjectEvent(vehicle,
                               previousVehicleState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);

    return vehicle;
  }

  /**
   * Sets a vehicle's next position.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param newPosition A reference to the point the vehicle is expected to
   * occupy next.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleNextPosition(TCSObjectReference<Vehicle> ref,
                                        TCSObjectReference<Point> newPosition)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withNextPosition(newPosition));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's precise position.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param newPosition The vehicle's precise position.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehiclePrecisePosition(TCSObjectReference<Vehicle> ref,
                                           Triple newPosition)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withPrecisePosition(newPosition));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's current orientation angle.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param angle The vehicle's orientation angle.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleOrientationAngle(TCSObjectReference<Vehicle> ref,
                                            double angle)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, ref);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withOrientationAngle(angle));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's transport order.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param orderRef A reference to the transport order the vehicle processes.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleTransportOrder(TCSObjectReference<Vehicle> vehicleRef,
                                          TCSObjectReference<TransportOrder> orderRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
    Vehicle previousState = vehicle;
    if (orderRef == null) {
      vehicle = objectPool.replaceObject(vehicle.withTransportOrder(null));
    }
    else {
      TransportOrder order = objectPool.getObject(TransportOrder.class, orderRef);
      vehicle = objectPool.replaceObject(vehicle.withTransportOrder(order.getReference()));
    }
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's order sequence.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param seqRef A reference to the order sequence the vehicle processes.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleOrderSequence(TCSObjectReference<Vehicle> vehicleRef,
                                         TCSObjectReference<OrderSequence> seqRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
    Vehicle previousState = vehicle;
    if (seqRef == null) {
      vehicle = objectPool.replaceObject(vehicle.withOrderSequence(null));
    }
    else {
      OrderSequence seq = objectPool.getObject(OrderSequence.class, seqRef);
      vehicle = objectPool.replaceObject(vehicle.withOrderSequence(seq.getReference()));
    }
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's index of the last route step travelled for the current
   * drive order of its current transport order.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param index The new index.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleRouteProgressIndex(TCSObjectReference<Vehicle> vehicleRef,
                                              int index)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withRouteProgressIndex(index));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's claimed resources.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param resources The new resources.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleClaimedResources(TCSObjectReference<Vehicle> vehicleRef,
                                            List<Set<TCSResourceReference<?>>> resources)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withClaimedResources(unmodifiableCopy(resources)));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Sets a vehicle's allocated resources.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param resources The new resources.
   * @return The modified vehicle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  public Vehicle setVehicleAllocatedResources(TCSObjectReference<Vehicle> vehicleRef,
                                              List<Set<TCSResourceReference<?>>> resources)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Vehicle vehicle = objectPool.getObject(Vehicle.class, vehicleRef);
    Vehicle previousState = vehicle;
    vehicle = objectPool.replaceObject(vehicle.withAllocatedResources(unmodifiableCopy(resources)));
    objectPool.emitObjectEvent(vehicle,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return vehicle;
  }

  /**
   * Creates a new block with a unique name and all other attributes set to
   * default values.
   *
   * @param to The transfer object from which to create the new block.
   * @return The newly created block.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  public Block createBlock(BlockCreationTO to)
      throws ObjectExistsException, ObjectUnknownException {
    Set<TCSResourceReference<?>> members = new HashSet<>();
    for (String memberName : to.getMemberNames()) {
      TCSObject<?> object = objectPool.getObject(memberName);
      if (!(object instanceof TCSResource)) {
        throw new ObjectUnknownException(memberName);
      }
      members.add(((TCSResource) object).getReference());
    }
    Block newBlock = new Block(to.getName())
        .withType(to.getType())
        .withMembers(members)
        .withProperties(to.getProperties())
        .withLayout(new Block.Layout(to.getLayout().getColor()));
    objectPool.addObject(newBlock);
    objectPool.emitObjectEvent(newBlock,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);
    // Return the newly created block.
    return newBlock;
  }

  /**
   * Creates a new group with a unique name and all other attributes set to
   * default values.
   *
   * @param to The transfer object from which to create the new group.
   * @return The newly created group.
   * @throws ObjectExistsException If an object with the new object's name already exists.
   * @throws ObjectUnknownException If any object referenced in the TO does not exist.
   */
  @Deprecated
  public org.opentcs.data.model.Group createGroup(org.opentcs.access.to.model.GroupCreationTO to)
      throws ObjectExistsException, ObjectUnknownException {
    Set<TCSObjectReference<?>> members = new HashSet<>();
    for (String memberName : to.getMemberNames()) {
      TCSObject<?> object = objectPool.getObject(memberName);
      if (object == null) {
        throw new ObjectUnknownException(memberName);
      }
      members.add(object.getReference());
    }
    org.opentcs.data.model.Group newGroup = new org.opentcs.data.model.Group(to.getName())
        .withMembers(members)
        .withProperties(to.getProperties());
    objectPool.addObject(newGroup);
    objectPool.emitObjectEvent(newGroup,
                               null,
                               TCSObjectEvent.Type.OBJECT_CREATED);
    // Return the newly created group.
    return newGroup;
  }

  /**
   * Returns a PlantModelCreationTO for this model.
   *
   * @return A PlantModelCreationTO for this model.
   */
  @SuppressWarnings("deprecation")
  public PlantModelCreationTO createPlantModelCreationTO() {
    return new PlantModelCreationTO(name)
        .withProperties(getProperties())
        .withPoints(getPoints())
        .withPaths(getPaths())
        .withVehicles(getVehicles())
        .withLocationTypes(getLocationTypes())
        .withLocations(getLocations())
        .withBlocks(getBlocks())
        .withGroups(getGroups())
        .withVisualLayout(getVisualLayout());
  }

  private List<PeripheralOperation> mapPeripheralOperationTOs(
      List<PeripheralOperationCreationTO> creationTOs) {
    return creationTOs.stream()
        .map(
            operationTO -> new PeripheralOperation(
                objectPool.getObject(Location.class,
                                     operationTO.getLocationName()).getReference(),
                operationTO.getOperation(),
                operationTO.getExecutionTrigger(),
                operationTO.isCompletionRequired())
        )
        .collect(Collectors.toList());
  }

  /**
   * Returns a list of {@link PointCreationTO Points} for all points in a model.
   *
   * @return A list of {@link PointCreationTO Points} for all points in a model.
   */
  private List<PointCreationTO> getPoints() {
    Set<Point> points = objectPool.getObjects(Point.class);
    List<PointCreationTO> result = new ArrayList<>();

    for (Point curPoint : points) {
      result.add(
          new PointCreationTO(curPoint.getName())
              .withPosition(curPoint.getPosition())
              .withVehicleOrientationAngle(curPoint.getVehicleOrientationAngle())
              .withType(curPoint.getType())
              .withProperties(curPoint.getProperties())
              .withLayout(new PointCreationTO.Layout(curPoint.getLayout().getPosition(),
                                                     curPoint.getLayout().getLabelOffset(),
                                                     curPoint.getLayout().getLayerId()))
      );
    }

    return result;
  }

  /**
   * Returns a list of {@link PathCreationTO Paths} for all paths in a model.
   *
   * @param model The model data.
   * @return A list of {@link PathCreationTO Paths} for all paths in a model.
   */
  @SuppressWarnings("deprecation")
  private List<PathCreationTO> getPaths() {
    Set<Path> paths = objectPool.getObjects(Path.class);
    List<PathCreationTO> result = new ArrayList<>();

    for (Path curPath : paths) {
      result.add(
          new PathCreationTO(curPath.getName(),
                             curPath.getSourcePoint().getName(),
                             curPath.getDestinationPoint().getName())
              .withLength(curPath.getLength())
              .withMaxVelocity(curPath.getMaxVelocity())
              .withMaxReverseVelocity(curPath.getMaxReverseVelocity())
              .withLocked(curPath.isLocked())
              .withPeripheralOperations(getPeripheralOperations(curPath))
              .withProperties(curPath.getProperties())
              .withLayout(new PathCreationTO.Layout(curPath.getLayout().getConnectionType(),
                                                    curPath.getLayout().getControlPoints(),
                                                    curPath.getLayout().getLayerId()))
      );
    }

    return result;
  }

  private List<PeripheralOperationCreationTO> getPeripheralOperations(Path path) {
    return path.getPeripheralOperations().stream()
        .map(op
            -> new PeripheralOperationCreationTO(op.getOperation(), op.getLocation().getName())
            .withExecutionTrigger(op.getExecutionTrigger())
            .withCompletionRequired(op.isCompletionRequired())
        )
        .collect(Collectors.toList());
  }

  /**
   * Returns a list of {@link VehicleCreationTO Vehicles} for all vehicles in a model.
   *
   * @param model The model data.
   * @return A list of {@link VehicleCreationTO Vehicles} for all vehicles in a model.
   */
  private List<VehicleCreationTO> getVehicles() {
    Set<Vehicle> vehicles = objectPool.getObjects(Vehicle.class);
    List<VehicleCreationTO> result = new ArrayList<>();

    for (Vehicle vehicle : vehicles) {
      result.add(
          new VehicleCreationTO(vehicle.getName())
              .withLength(vehicle.getLength())
              .withEnergyLevelGood(vehicle.getEnergyLevelGood())
              .withEnergyLevelCritical(vehicle.getEnergyLevelCritical())
              .withEnergyLevelFullyRecharged(vehicle.getEnergyLevelFullyRecharged())
              .withEnergyLevelSufficientlyRecharged(vehicle.getEnergyLevelSufficientlyRecharged())
              .withMaxVelocity(vehicle.getMaxVelocity())
              .withMaxReverseVelocity(vehicle.getMaxReverseVelocity())
              .withProperties(vehicle.getProperties())
              .withLayout(new VehicleCreationTO.Layout(vehicle.getLayout().getRouteColor()))
      );
    }

    return result;
  }

  /**
   * Returns a list of {@link LocationTypeCreationTO LocationTypes} for all location types in a
   * model.
   *
   * @param model The model data.
   * @return A list of {@link LocationTypeCreationTO LocationTypes} for all location types in a
   * model.
   */
  private List<LocationTypeCreationTO> getLocationTypes() {
    Set<LocationType> locTypes = objectPool.getObjects(LocationType.class);
    List<LocationTypeCreationTO> result = new ArrayList<>();

    for (LocationType curType : locTypes) {
      result.add(
          new LocationTypeCreationTO(curType.getName())
              .withAllowedOperations(curType.getAllowedOperations())
              .withAllowedPeripheralOperations(curType.getAllowedPeripheralOperations())
              .withProperties(curType.getProperties())
              .withLayout(
                  new LocationTypeCreationTO.Layout(curType.getLayout().getLocationRepresentation())
              )
      );
    }

    return result;
  }

  /**
   * Returns a list of {@link LocationCreationTO Locations} for all locations in a model.
   *
   * @param model The model data.
   * @return A list of {@link LocationCreationTO Locations} for all locations in a model.
   */
  private List<LocationCreationTO> getLocations() {
    Set<Location> locations = objectPool.getObjects(Location.class);
    List<LocationCreationTO> result = new ArrayList<>();

    for (Location curLoc : locations) {
      result.add(
          new LocationCreationTO(curLoc.getName(),
                                 curLoc.getType().getName(),
                                 curLoc.getPosition())
              .withLinks(curLoc.getAttachedLinks().stream()
                  .collect(Collectors.toMap(link -> link.getPoint().getName(),
                                            Location.Link::getAllowedOperations)))
              .withLocked(curLoc.isLocked())
              .withProperties(curLoc.getProperties())
              .withLayout(
                  new LocationCreationTO.Layout(curLoc.getLayout().getPosition(),
                                                curLoc.getLayout().getLabelOffset(),
                                                curLoc.getLayout().getLocationRepresentation(),
                                                curLoc.getLayout().getLayerId())
              )
      );
    }

    return result;
  }

  /**
   * Returns a list of {@link BlockCreationTO Blocks} for all blocks in a model.
   *
   * @param model The model data.
   * @return A list of {@link BlockCreationTO Blocks} for all blocks in a model.
   */
  private List<BlockCreationTO> getBlocks() {
    Set<Block> blocks = objectPool.getObjects(Block.class);
    List<BlockCreationTO> result = new ArrayList<>();

    for (Block curBlock : blocks) {
      result.add(
          new BlockCreationTO(curBlock.getName())
              .withMemberNames(curBlock.getMembers().stream()
                  .map(member -> member.getName())
                  .collect(Collectors.toSet()))
              .withType(curBlock.getType())
              .withProperties(curBlock.getProperties())
              .withLayout(new BlockCreationTO.Layout(curBlock.getLayout().getColor()))
      );
    }

    return result;
  }

  /**
   * Returns a list of GroupCreationTOs for all groups in a model.
   *
   * @param model The model data.
   * @return A list of GroupCreationTOs for all groups in a model.
   */
  @Deprecated
  private List<org.opentcs.access.to.model.GroupCreationTO> getGroups() {
    Set<org.opentcs.data.model.Group> groups
        = objectPool.getObjects(org.opentcs.data.model.Group.class);
    List<org.opentcs.access.to.model.GroupCreationTO> result = new ArrayList<>();

    for (org.opentcs.data.model.Group curGroup : groups) {
      result.add(
          new org.opentcs.access.to.model.GroupCreationTO(curGroup.getName())
              .withMemberNames(curGroup.getMembers().stream()
                  .map(member -> member.getName())
                  .collect(Collectors.toSet()))
              .withProperties(curGroup.getProperties())
      );
    }

    return result;
  }

  /**
   * Returns a {@link VisualLayoutCreationTO} for the visual layouts in a model.
   *
   * @param model The model data.
   * @return A {@link VisualLayoutCreationTO} for the visual layouts in a model.
   */
  private VisualLayoutCreationTO getVisualLayout() {
    Set<VisualLayout> layouts = objectPool.getObjects(VisualLayout.class);
    checkState(layouts.size() == 1,
               "There has to be one, and only one, visual layout. Number of visual layouts: %d",
               layouts.size());
    VisualLayout layout = layouts.iterator().next();

    return new VisualLayoutCreationTO(layout.getName())
        .withScaleX(layout.getScaleX())
        .withScaleY(layout.getScaleY())
        .withProperties(layout.getProperties())
        .withLayers(layout.getLayers())
        .withLayerGroups(layout.getLayerGroups());
  }

  /**
   * Expands a set of resources <em>A</em> to a set of resources <em>B</em>.
   * <em>B</em> contains the resources in <em>A</em> with blocks expanded to
   * their actual members.
   * The given set is not modified.
   *
   * @param resources The set of resources to be expanded.
   * @return The given set with resources expanded.
   * @throws ObjectUnknownException If an object referenced in the given set
   * does not exist.
   */
  public Set<TCSResource<?>> expandResources(Set<TCSResourceReference<?>> resources)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Set<TCSResource<?>> result = new HashSet<>();
    Set<Block> blocks = getObjectPool().getObjects(Block.class);
    for (TCSResourceReference<?> curRef : resources) {
      TCSObject<?> object = objectPool.getObject(curRef);
      TCSResource<?> resource = (TCSResource<?>) object;
      result.add(resource);
      for (Block curBlock : blocks) {
        // If the current block contains the resource, add all of the block's
        // members to the result.
        if (curBlock.getMembers().contains(resource.getReference())) {
          for (TCSResourceReference<?> curResRef : curBlock.getMembers()) {
            TCSResource<?> member = (TCSResource<?>) objectPool.getObject(curResRef);
            result.add(member);
          }
        }
      }
    }
    return result;
  }

  /**
   * Overrides the layout data in {@code TCSObject}s with the data stored in their respective
   * model layout element.
   *
   * @param layout The visual layout to get the layout data from.
   */
  @Deprecated
  @ScheduledApiChange(details = "Will be removed.", when = "6.0")
  private void overrideLayoutData(VisualLayoutCreationTO layout) {
    for (org.opentcs.access.to.model.ModelLayoutElementCreationTO mleTO : layout.getModelElements()) {
      TCSObject<?> object = objectPool.getObject(mleTO.getName());
      Map<String, String> props = mleTO.getProperties();

      if (object instanceof Point) {
        overridePointLayoutData((Point) object, props);
      }
      else if (object instanceof Path) {
        overridePathLayoutData((Path) object, props);
      }
      else if (object instanceof Location) {
        overrideLocationLayoutData((Location) object, props);
      }
      else if (object instanceof Block) {
        overrideBlockLayoutData((Block) object, props);
      }
      else if (object instanceof Vehicle) {
        overrideVehicleLayoutData((Vehicle) object, props);
      }
    }
  }

  private void overridePointLayoutData(Point oldPoint, Map<String, String> properties)
      throws NumberFormatException {
    long positionX = properties.get(ElementPropKeys.POINT_POS_X) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.POINT_POS_X))
        : oldPoint.getLayout().getPosition().getX();
    long positionY = properties.get(ElementPropKeys.POINT_POS_Y) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.POINT_POS_Y))
        : oldPoint.getLayout().getPosition().getY();
    long labelOffsetX = properties.get(ElementPropKeys.POINT_LABEL_OFFSET_X) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.POINT_LABEL_OFFSET_X))
        : oldPoint.getLayout().getLabelOffset().getX();
    long labelOffsetY = properties.get(ElementPropKeys.POINT_LABEL_OFFSET_Y) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.POINT_LABEL_OFFSET_Y))
        : oldPoint.getLayout().getLabelOffset().getY();
    Point newPoint = oldPoint.withLayout(
        new Point.Layout(new Couple(positionX, positionY),
                         new Couple(labelOffsetX, labelOffsetY),
                         oldPoint.getLayout().getLayerId())
    );
    objectPool.replaceObject(newPoint);
    objectPool.emitObjectEvent(newPoint, oldPoint, TCSObjectEvent.Type.OBJECT_MODIFIED);
  }

  private void overridePathLayoutData(Path oldPath, Map<String, String> properties)
      throws IllegalArgumentException {
    String connectionTypeString
        = properties.getOrDefault(ElementPropKeys.PATH_CONN_TYPE,
                                  oldPath.getLayout().getConnectionType().name());
    Path.Layout.ConnectionType connectionType;
    switch (connectionTypeString) {
      case "DIRECT":
        connectionType = Path.Layout.ConnectionType.DIRECT;
        break;
      case "ELBOW":
        connectionType = Path.Layout.ConnectionType.ELBOW;
        break;
      case "SLANTED":
        connectionType = Path.Layout.ConnectionType.SLANTED;
        break;
      case "POLYPATH":
        connectionType = Path.Layout.ConnectionType.POLYPATH;
        break;
      case "BEZIER":
        connectionType = Path.Layout.ConnectionType.BEZIER;
        break;
      case "BEZIER_3":
        connectionType = Path.Layout.ConnectionType.BEZIER_3;
        break;
      default:
        throw new IllegalArgumentException("Unhandled connection type: " + connectionTypeString);
    }

    List<Couple> controlPoints = oldPath.getLayout().getControlPoints();
    String controlPointsString = properties.get(ElementPropKeys.PATH_CONTROL_POINTS);
    if (controlPointsString != null) {
      controlPoints = Arrays.asList(controlPointsString.split(";")).stream()
          .map(controlPointString -> {
            String[] coordinateStrings = controlPointString.split(",");
            return new Couple(Long.parseLong(coordinateStrings[0]),
                              Long.parseLong(coordinateStrings[1]));
          })
          .collect(Collectors.toList());
    }

    Path newPath = oldPath.withLayout(new Path.Layout(connectionType,
                                                      controlPoints,
                                                      oldPath.getLayout().getLayerId()));

    objectPool.replaceObject(newPath);
    objectPool.emitObjectEvent(newPath, oldPath, TCSObjectEvent.Type.OBJECT_MODIFIED);
  }

  private void overrideLocationLayoutData(Location oldLocation, Map<String, String> properties)
      throws NumberFormatException {
    long positionX = properties.get(ElementPropKeys.LOC_POS_X) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.LOC_POS_X))
        : oldLocation.getLayout().getPosition().getX();
    long positionY = properties.get(ElementPropKeys.LOC_POS_Y) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.LOC_POS_Y))
        : oldLocation.getLayout().getPosition().getY();
    long labelOffsetX = properties.get(ElementPropKeys.LOC_LABEL_OFFSET_X) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.LOC_LABEL_OFFSET_X))
        : oldLocation.getLayout().getLabelOffset().getX();
    long labelOffsetY = properties.get(ElementPropKeys.LOC_LABEL_OFFSET_Y) != null
        ? Integer.parseInt(properties.get(ElementPropKeys.LOC_LABEL_OFFSET_Y))
        : oldLocation.getLayout().getLabelOffset().getY();
    Location newLocation = oldLocation.withLayout(
        new Location.Layout(new Couple(positionX, positionY),
                            new Couple(labelOffsetX, labelOffsetY),
                            oldLocation.getLayout().getLocationRepresentation(),
                            oldLocation.getLayout().getLayerId())
    );
    objectPool.replaceObject(newLocation);
    objectPool.emitObjectEvent(newLocation, oldLocation, TCSObjectEvent.Type.OBJECT_MODIFIED);
  }

  private void overrideBlockLayoutData(Block oldBlock, Map<String, String> properties)
      throws NumberFormatException {
    Color color = properties.get(ElementPropKeys.BLOCK_COLOR) != null
        ? Colors.decodeFromHexRGB(properties.get(ElementPropKeys.BLOCK_COLOR))
        : oldBlock.getLayout().getColor();
    Block newBlock = oldBlock.withLayout(new Block.Layout(color));
    objectPool.replaceObject(newBlock);
    objectPool.emitObjectEvent(newBlock, oldBlock, TCSObjectEvent.Type.OBJECT_MODIFIED);
  }

  private void overrideVehicleLayoutData(TCSObject<?> object, Map<String, String> properties)
      throws NumberFormatException {
    Vehicle oldVehicle = (Vehicle) object;
    Color routeColor = properties.get(ElementPropKeys.VEHICLE_ROUTE_COLOR) != null
        ? Colors.decodeFromHexRGB(properties.get(ElementPropKeys.VEHICLE_ROUTE_COLOR))
        : oldVehicle.getLayout().getRouteColor();
    Vehicle newVehicle = oldVehicle.withLayout(new Vehicle.Layout(routeColor));
    objectPool.replaceObject(newVehicle);
    objectPool.emitObjectEvent(newVehicle, oldVehicle, TCSObjectEvent.Type.OBJECT_MODIFIED);
  }

  /**
   * Adds an incoming path to a point.
   *
   * @param pointRef A reference to the point to be modified.
   * @param pathRef A reference to the path.
   * @return The modified point.
   * @throws ObjectUnknownException If the referenced point or path do not
   * exist.
   */
  private Point addPointIncomingPath(TCSObjectReference<Point> pointRef,
                                     TCSObjectReference<Path> pathRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Point point = objectPool.getObject(Point.class, pointRef);
    Path path = objectPool.getObject(Path.class, pathRef);
    // Check if the point really is the path's destination point.
    if (!path.getDestinationPoint().equals(point.getReference())) {
      throw new IllegalArgumentException("Point is not the path's destination.");
    }
    Path previousState = path;
    Set<TCSObjectReference<Path>> incomingPaths = new HashSet<>(point.getIncomingPaths());
    incomingPaths.add(path.getReference());
    point = objectPool.replaceObject(point.withIncomingPaths(incomingPaths));
    objectPool.emitObjectEvent(point,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return point;
  }

  /**
   * Adds an outgoing path to a point.
   *
   * @param pointRef A reference to the point to be modified.
   * @param pathRef A reference to the path.
   * @return The modified point.
   * @throws ObjectUnknownException If the referenced point or path do not
   * exist.
   */
  private Point addPointOutgoingPath(TCSObjectReference<Point> pointRef,
                                     TCSObjectReference<Path> pathRef)
      throws ObjectUnknownException {
    LOG.debug("method entry");
    Point point = objectPool.getObject(Point.class, pointRef);
    Path path = objectPool.getObject(Path.class, pathRef);
    // Check if the point really is the path's source.
    if (!path.getSourcePoint().equals(point.getReference())) {
      throw new IllegalArgumentException("Point is not the path's source.");
    }
    Path previousState = path;
    Set<TCSObjectReference<Path>> outgoingPaths = new HashSet<>(point.getOutgoingPaths());
    outgoingPaths.add(path.getReference());
    point = objectPool.replaceObject(point.withOutgoingPaths(outgoingPaths));
    objectPool.emitObjectEvent(point,
                               previousState,
                               TCSObjectEvent.Type.OBJECT_MODIFIED);
    return point;
  }

  private static List<Set<TCSResourceReference<?>>> unmodifiableCopy(
      List<Set<TCSResourceReference<?>>> resources) {
    List<Set<TCSResourceReference<?>>> result = new ArrayList<>();

    for (Set<TCSResourceReference<?>> resSet : resources) {
      result.add(Set.copyOf(resSet));
    }

    return Collections.unmodifiableList(result);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/FullDispatchTask.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.strategies.basic.peripherals.dispatching.phase.AssignFreePeripheralsPhase;
import org.opentcs.strategies.basic.peripherals.dispatching.phase.AssignReservedPeripheralsPhase;
import org.opentcs.strategies.basic.peripherals.dispatching.phase.ReleasePeripheralsPhase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Performs a full dispatch run.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FullDispatchTask
    implements Runnable,
               Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(FullDispatchTask.class);

  private final AssignReservedPeripheralsPhase assignReservedPeripheralsPhase;
  private final ReleasePeripheralsPhase releasePeripheralsPhase;
  private final AssignFreePeripheralsPhase assignFreePeripheralsPhase;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  @Inject
  public FullDispatchTask(AssignReservedPeripheralsPhase assignReservedPeripheralsPhase,
                          ReleasePeripheralsPhase releasePeripheralsPhase,
                          AssignFreePeripheralsPhase assignFreePeripheralsPhase) {
    this.assignReservedPeripheralsPhase = requireNonNull(assignReservedPeripheralsPhase,
                                                         "assignReservedPeripheralsPhase");
    this.releasePeripheralsPhase = requireNonNull(releasePeripheralsPhase, 
                                                  "releasePeripheralsPhase");
    this.assignFreePeripheralsPhase = requireNonNull(assignFreePeripheralsPhase,
                                                     "assignFreePeripheralsPhase");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    assignReservedPeripheralsPhase.initialize();
    releasePeripheralsPhase.initialize();
    assignFreePeripheralsPhase.initialize();

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    assignFreePeripheralsPhase.terminate();
    releasePeripheralsPhase.terminate();
    assignReservedPeripheralsPhase.terminate();

    initialized = false;
  }

  @Override
  public void run() {
    LOG.debug("Starting full dispatch run...");

    // XXX Add a finishWithdrawalsPhase?
    assignReservedPeripheralsPhase.run();
    releasePeripheralsPhase.run();
    assignFreePeripheralsPhase.run();

    LOG.debug("Finished full dispatch run.");
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerGroupManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Organizes the layer groups in a plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerGroupManager
    extends LayerGroupEditor {

  /**
   * Add a listener to the set that's notified each time a change to group data occurs.
   *
   * @param listener The listener to add.
   */
  void addLayerGroupChangeListener(LayerGroupChangeListener listener);
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/ApplicationPortal.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange;

import static java.util.Objects.requireNonNull;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.SharedKernelServicePortal;
import static org.opentcs.util.Assertions.checkState;

/**
 * Implementation of the {@link SharedKernelServicePortal} interface to give access to a shared portal object.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class ApplicationPortal
    implements SharedKernelServicePortal {

  /**
   * The portal.
   */
  private final KernelServicePortal portal;
  /**
   * The portal provider instance that this client is registered at.
   */
  private final ApplicationPortalProvider sharedPortalProvider;
  /**
   * The object registered with the provider.
   */
  private final Object registeredToken;
  /**
   * Indicates whether this instance is closed or not.
   */
  private boolean closed;

  /**
   * Creates a new instance.
   *
   * @param portal The shared portal instance.
   * @param portalProvider The provider this client is registered with.
   * @param registeredToken The token that is actually registered with the provider.
   */
  public ApplicationPortal(KernelServicePortal portal,
                           ApplicationPortalProvider portalProvider,
                           Object registeredToken) {
    this.portal = requireNonNull(portal, "portal");
    this.sharedPortalProvider = requireNonNull(portalProvider, "portalProvider");
    this.registeredToken = requireNonNull(registeredToken, "registeredToken");
  }

  @Override
  public void close() {
    if (isClosed()) {
      return;
    }

    sharedPortalProvider.unregister(registeredToken);
    closed = true;
  }

  @Override
  public boolean isClosed() {
    return closed;
  }

  @Override
  public KernelServicePortal getPortal()
      throws IllegalStateException {
    checkState(!isClosed(), "Closed already.");

    return portal;
  }
}


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/test/java/org/opentcs/kernel/extensions/servicewebapi/AuthenticatorTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.servicewebapi;

import org.junit.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import spark.Request;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AuthenticatorTest {

  private ServiceWebApiConfiguration configuration;

  private Authenticator authenticator;

  @Before
  public void setUp() {
    configuration = mock(ServiceWebApiConfiguration.class);
    authenticator = new Authenticator(configuration);
  }

  @Test
  public void allowRequestsIfNoAccessKeyConfigured() {
    when(configuration.accessKey()).thenReturn("");

    assertTrue(authenticator.isAuthenticated(aRequestWithAccessKey(null)));
    assertTrue(authenticator.isAuthenticated(aRequestWithAccessKey("")));
    assertTrue(authenticator.isAuthenticated(aRequestWithAccessKey("some random value")));
  }

  @Test
  public void allowRequestIfCorrectAccessKeyGiven() {
    when(configuration.accessKey()).thenReturn("my access key");

    assertTrue(authenticator.isAuthenticated(aRequestWithAccessKey("my access key")));
  }

  @Test
  public void disallowRequestIfWrongAccessKeyGiven() {
    when(configuration.accessKey()).thenReturn("my access key");

    assertFalse(authenticator.isAuthenticated(aRequestWithAccessKey(null)));
    assertFalse(authenticator.isAuthenticated(aRequestWithAccessKey("")));
    assertFalse(authenticator.isAuthenticated(aRequestWithAccessKey("some random value")));
  }

  private Request aRequestWithAccessKey(String accessKey) {
    Request request = mock(Request.class);

    when(request.headers(HttpConstants.HEADER_NAME_ACCESS_KEY)).thenReturn(accessKey);

    return request;
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/DefaultDispatcher.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.components.kernel.services.InternalVehicleService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import static org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration.RerouteTrigger.TOPOLOGY_CHANGE;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Dispatches transport orders and vehicles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultDispatcher
    implements Dispatcher {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultDispatcher.class);
  /**
   * Stores reservations of transport orders for vehicles.
   */
  private final OrderReservationPool orderReservationPool;
  /**
   * Provides services/utility methods for working with transport orders.
   */
  private final TransportOrderUtil transportOrderUtil;
  /**
   * The transport order service.
   */
  private final InternalTransportOrderService transportOrderService;
  /**
   * The vehicle service.
   */
  private final InternalVehicleService vehicleService;
  /**
   * Where we register for application events.
   */
  private final EventSource eventSource;
  /**
   * The kernel's executor.
   */
  private final ScheduledExecutorService kernelExecutor;

  private final FullDispatchTask fullDispatchTask;

  private final Provider<PeriodicVehicleRedispatchingTask> periodicDispatchTaskProvider;

  private final DefaultDispatcherConfiguration configuration;

  private final RerouteUtil rerouteUtil;
  /**
   *
   */
  private ImplicitDispatchTrigger implicitDispatchTrigger;

  private ScheduledFuture<?> periodicDispatchTaskFuture;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param orderReservationPool Stores reservations of transport orders for vehicles.
   * @param transportOrderUtil Provides services for working with transport orders.
   * @param transportOrderService The transport order service.
   * @param vehicleService The vehicle service.
   * @param eventSource Where this instance registers for application events.
   * @param kernelExecutor Executes dispatching tasks.
   * @param fullDispatchTask The full dispatch task.
   * @param periodicDispatchTaskProvider Provides the periodic vehicle redospatching task.
   * @param configuration The dispatcher configuration.
   * @param rerouteUtil The reroute util.
   */
  @Inject
  public DefaultDispatcher(OrderReservationPool orderReservationPool,
                           TransportOrderUtil transportOrderUtil,
                           InternalTransportOrderService transportOrderService,
                           InternalVehicleService vehicleService,
                           @ApplicationEventBus EventSource eventSource,
                           @KernelExecutor ScheduledExecutorService kernelExecutor,
                           FullDispatchTask fullDispatchTask,
                           Provider<PeriodicVehicleRedispatchingTask> periodicDispatchTaskProvider,
                           DefaultDispatcherConfiguration configuration,
                           RerouteUtil rerouteUtil) {
    this.orderReservationPool = requireNonNull(orderReservationPool, "orderReservationPool");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
    this.transportOrderService = requireNonNull(transportOrderService, "transportOrderService");
    this.vehicleService = requireNonNull(vehicleService, "vehicleService");
    this.eventSource = requireNonNull(eventSource, "eventSource");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
    this.fullDispatchTask = requireNonNull(fullDispatchTask, "fullDispatchTask");
    this.periodicDispatchTaskProvider = requireNonNull(periodicDispatchTaskProvider,
                                                       "periodicDispatchTaskProvider");
    this.configuration = requireNonNull(configuration, "configuration");
    this.rerouteUtil = requireNonNull(rerouteUtil, "rerouteUtil");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    LOG.debug("Initializing...");

    transportOrderUtil.initialize();
    orderReservationPool.clear();

    fullDispatchTask.initialize();

    implicitDispatchTrigger = new ImplicitDispatchTrigger(this);
    eventSource.subscribe(implicitDispatchTrigger);

    LOG.debug("Scheduling periodic dispatch task with interval of {} ms...",
              configuration.idleVehicleRedispatchingInterval());
    periodicDispatchTaskFuture = kernelExecutor.scheduleAtFixedRate(
        periodicDispatchTaskProvider.get(),
        configuration.idleVehicleRedispatchingInterval(),
        configuration.idleVehicleRedispatchingInterval(),
        TimeUnit.MILLISECONDS
    );

    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    LOG.debug("Terminating...");

    periodicDispatchTaskFuture.cancel(false);
    periodicDispatchTaskFuture = null;

    eventSource.unsubscribe(implicitDispatchTrigger);
    implicitDispatchTrigger = null;

    fullDispatchTask.terminate();

    initialized = false;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void dispatch() {
    LOG.debug("Scheduling dispatch task...");
    // Schedule this to be executed by the kernel executor.
    kernelExecutor.submit(fullDispatchTask);
  }

  @Override
  public void withdrawOrder(TransportOrder order, boolean immediateAbort) {
    requireNonNull(order, "order");
    checkState(isInitialized(), "Not initialized");

    // Schedule this to be executed by the kernel executor.
    kernelExecutor.submit(() -> {
      LOG.debug("Scheduling withdrawal for transport order '{}' (immediate={})...",
                order.getName(),
                immediateAbort);
      transportOrderUtil.abortOrder(order, immediateAbort, false);
    });
  }

  @Override
  public void withdrawOrder(Vehicle vehicle, boolean immediateAbort) {
    requireNonNull(vehicle, "vehicle");
    checkState(isInitialized(), "Not initialized");

    // Schedule this to be executed by the kernel executor.
    kernelExecutor.submit(() -> {
      LOG.debug("Scheduling withdrawal for vehicle '{}' (immediate={})...",
                vehicle.getName(),
                immediateAbort);
      transportOrderUtil.abortOrder(vehicle, immediateAbort, false, false);
    });
  }

  @Override
  public void topologyChanged() {
    if (configuration.rerouteTrigger() == TOPOLOGY_CHANGE) {
      LOG.debug("Scheduling reroute task...");
      kernelExecutor.submit(() -> {
        LOG.debug("Rerouting vehicles due to topology change...");
        rerouteUtil.reroute(vehicleService.fetchObjects(Vehicle.class));
      });
    }
  }

  private static boolean vehicleDispatchable(Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");

    if (vehicle.getCurrentPosition() == null) {
      LOG.debug("Vehicle '{}' unknown position -> not dispatchable", vehicle.getName());
      return false;
    }
    if (vehicle.getIntegrationLevel() != Vehicle.IntegrationLevel.TO_BE_UTILIZED) {
      LOG.debug("Vehicle '{}' is not to be utilized.", vehicle.getName());
      return false;
    }
    // ProcState IDLE, State CHARGING and energy level not high enough? Then let
    // it charge a bit longer.
    if (vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && vehicle.hasState(Vehicle.State.CHARGING)
        && vehicle.isEnergyLevelCritical()) {
      LOG.debug("Vehicle '{}' is CHARGING, energy level {}<={} -> not (yet) dispatchable.",
                vehicle.getName(),
                vehicle.getEnergyLevel(),
                vehicle.getEnergyLevelCritical());
      return false;
    }
    // Only dispatch vehicles that are either not processing any order at all or
    // are waiting for the next drive order.
    if (!vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && !vehicle.hasProcState(Vehicle.ProcState.AWAITING_ORDER)) {
      LOG.debug("Vehicle '{}' is in processing state {} -> not dispatchable",
                vehicle.getName(),
                vehicle.getProcState());
      return false;
    }
    return true;
  }

}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/ImplicitDispatchTriggerTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import org.junit.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ImplicitDispatchTriggerTest {

  private Dispatcher dispatcher;

  private ImplicitDispatchTrigger listener;

  @Before
  public void setUp() {
    dispatcher = mock(Dispatcher.class);
    listener = new ImplicitDispatchTrigger(dispatcher);
  }

  @Test
  public void dispatchWhenIdleAndEnergyLevelChanged() {
    Vehicle vehicleOld = new Vehicle("someVehicle")
        .withIntegrationLevel(Vehicle.IntegrationLevel.TO_BE_UTILIZED)
        .withProcState(Vehicle.ProcState.IDLE)
        .withState(Vehicle.State.IDLE)
        .withEnergyLevel(100);
    Vehicle vehicleNew = vehicleOld.withEnergyLevel(99);

    listener.onEvent(new TCSObjectEvent(vehicleNew,
                                        vehicleOld,
                                        TCSObjectEvent.Type.OBJECT_MODIFIED));

    verify(dispatcher).dispatch();
  }

  @Test
  public void noDispatchWhenNotIdleAndEnergyLevelChanged() {
    Vehicle vehicleOld = new Vehicle("someVehicle")
        .withIntegrationLevel(Vehicle.IntegrationLevel.TO_BE_UTILIZED)
        .withProcState(Vehicle.ProcState.PROCESSING_ORDER)
        .withState(Vehicle.State.EXECUTING)
        .withEnergyLevel(100);
    Vehicle vehicleNew = vehicleOld.withEnergyLevel(99);

    listener.onEvent(new TCSObjectEvent(vehicleNew,
                                        vehicleOld,
                                        TCSObjectEvent.Type.OBJECT_MODIFIED));

    verify(dispatcher, never()).dispatch();
  }

  @Test
  public void dispatchWhenProcStateBecameIdle() {
    Vehicle vehicleOld = new Vehicle("someVehicle")
        .withIntegrationLevel(Vehicle.IntegrationLevel.TO_BE_UTILIZED)
        .withProcState(Vehicle.ProcState.PROCESSING_ORDER)
        .withState(Vehicle.State.EXECUTING);
    Vehicle vehicleNew = vehicleOld.withProcState(Vehicle.ProcState.IDLE)
        .withState(Vehicle.State.IDLE);

    listener.onEvent(new TCSObjectEvent(vehicleNew,
                                        vehicleOld,
                                        TCSObjectEvent.Type.OBJECT_MODIFIED));

    verify(dispatcher).dispatch();
  }

  @Test
  public void dispatchWhenProcStateBecameAwaitingOrder() {
    Vehicle vehicleOld = new Vehicle("someVehicle")
        .withIntegrationLevel(Vehicle.IntegrationLevel.TO_BE_UTILIZED)
        .withProcState(Vehicle.ProcState.PROCESSING_ORDER);
    Vehicle vehicleNew = vehicleOld.withProcState(Vehicle.ProcState.AWAITING_ORDER);

    listener.onEvent(new TCSObjectEvent(vehicleNew,
                                        vehicleOld,
                                        TCSObjectEvent.Type.OBJECT_MODIFIED));

    verify(dispatcher).dispatch();
  }

  @Test
  public void dispatchWhenOrderSequenceNulled() {
    Vehicle vehicleOld = new Vehicle("someVehicle")
        .withIntegrationLevel(Vehicle.IntegrationLevel.TO_BE_UTILIZED)
        .withOrderSequence(new OrderSequence("someSequence").getReference());
    Vehicle vehicleNew = vehicleOld.withOrderSequence(null);

    listener.onEvent(new TCSObjectEvent(vehicleNew,
                                        vehicleOld,
                                        TCSObjectEvent.Type.OBJECT_MODIFIED));

    verify(dispatcher).dispatch();
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/event/SystemModelTransitionEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.event;

import java.util.EventObject;
import static java.util.Objects.requireNonNull;
import org.opentcs.guing.model.SystemModel;

/**
 * Informs listeners about the current system model being replaced with a
 * different one.
 * For every stage of the transition from the current/old system model to the
 * new one, a separate event is emitted.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SystemModelTransitionEvent
    extends EventObject {

  /**
   * The current stage of the transition.
   */
  private final Stage stage;
  /**
   * The system model to which this event refers.
   */
  private final SystemModel model;

  /**
   * Creates a new instance.
   *
   * @param source The originator of this event.
   * @param stage The current state of the transition.
   * @param model The system model to which this event refers.
   */
  public SystemModelTransitionEvent(Object source, Stage stage, SystemModel model) {
    super(source);
    this.stage = stage;
    this.model = requireNonNull(model, "model");
  }

  /**
   * Returns the current stage of the transition.
   *
   * @return The current stage of the transition.
   */
  public Stage getStage() {
    return stage;
  }

  /**
   * Returns the system model to which this event refers.
   *
   * @return The system model to which this event refers.
   */
  public SystemModel getModel() {
    return model;
  }

  @Override
  public String toString() {
    return "SystemModelTransitionEvent{"
        + "source=" + getSource() + ", "
        + "stage=" + stage + ", "
        + "model=" + model
        + '}';
  }

  public static enum Stage {

    /**
     * Indicates the current system model is currently being unloaded.
     */
    UNLOADING,
    /**
     * Indicates the current system model has been unloaded.
     */
    UNLOADED,
    /**
     * Indicates the new system model is being loaded.
     */
    LOADING,
    /**
     * Indicates the new system model has been loaded.
     */
    LOADED;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/parking/PrioritizedParkingPositionSupplierTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;

/**
 * Tests for {@link PrioritizedParkingPositionSupplier}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PrioritizedParkingPositionSupplierTest {

  private PrioritizedParkingPositionSupplier supplier;
  private InternalPlantModelService plantModelService;
  private Router router;
  private ParkingPositionToPriorityFunction priorityFunction;

  public PrioritizedParkingPositionSupplierTest() {
  }

  @Before
  public void setUp() {
    plantModelService = mock(InternalPlantModelService.class);
    router = mock(Router.class);
    priorityFunction = new ParkingPositionToPriorityFunction();
    supplier = new PrioritizedParkingPositionSupplier(plantModelService, router, priorityFunction);
  }

  @Test
  public void returnsPrioritizedParkingPosition() {
    Point point1 = new Point("vehicle's current position");
    Point point2 = new Point("parking position without priority")
        .withType(Point.Type.PARK_POSITION);
    Point point3 = new Point("parking position with priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "1");
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObject(Point.class, point1.getReference())).thenReturn(point1);
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));
    when(router.getCosts(vehicle, point1, point3)).thenReturn(1L);

    Optional<Point> result = supplier.findParkingPosition(vehicle);
    assertTrue("expected a prioritized parking position to be present", result.isPresent());
    assertEquals(point3, result.get());
  }

  @Test
  public void returnsClosestPrioritizedParkingPositionForPositionsWithSamePriority() {
    Point point1 = new Point("vehicle's current position");
    Point point2 = new Point("parking position with some priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "4");
    Point point3 = new Point("parking position with the same priority but closer to the vehicle")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "4");
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObject(Point.class, point1.getReference())).thenReturn(point1);
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));
    when(router.getCosts(vehicle, point1, point2)).thenReturn(10L);
    when(router.getCosts(vehicle, point1, point3)).thenReturn(1L);

    Optional<Point> result = supplier.findParkingPosition(vehicle);
    assertTrue("expected a prioritized parking position to be present", result.isPresent());
    assertEquals(point3, result.get());
  }

  @Test
  public void returnsHigherPrioritizedParkingPositionThanCurrentlyOccupying() {
    Point point1 = new Point("vehicle's current parking position with some priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "17");
    Point point2 = new Point("parking position with lower priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "20");
    Point point3 = new Point("parking position with higher priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "12");
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObject(Point.class, point1.getReference())).thenReturn(point1);
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));
    when(router.getCosts(vehicle, point1, point3)).thenReturn(1L);

    Optional<Point> result = supplier.findParkingPosition(vehicle);
    assertTrue("expected a prioritized parking position to be present", result.isPresent());
    assertEquals(point3, result.get());
  }

  @Test
  public void returnsEmptyForOnlyPositionsAvailableWithSamePriorityAsCurrentlyOccupying() {
    Point point1 = new Point("vehicle's current parking position with some priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "13");
    Point point2 = new Point("parking position with the same priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "13");
    Point point3 = new Point("another parking position with the same priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "13");
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObject(Point.class, point1.getReference())).thenReturn(point1);
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));

    Optional<Point> result = supplier.findParkingPosition(vehicle);
    assertFalse("expected no prioritized parking position to be present", result.isPresent());
  }

  @Test
  public void returnsEmptyForNoHigherPrioritizedParkingPositionsAvailable() {
    Point point1 = new Point("vehicle's current parking position with some priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "13");
    Point point2 = new Point("parking position with lower priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "24");
    Point point3 = new Point("another parking position with lower priority")
        .withType(Point.Type.PARK_POSITION)
        .withProperty(Dispatcher.PROPKEY_PARKING_POSITION_PRIORITY, "45");
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObject(Point.class, point1.getReference())).thenReturn(point1);
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));

    Optional<Point> result = supplier.findParkingPosition(vehicle);
    assertFalse("expected no prioritized parking position to be present", result.isPresent());
  }

  @Test
  public void returnsEmptyForNoPrioritizedParkingPositionAvailable() {
    Point point1 = new Point("vehicle's current position");
    Point point2 = new Point("parking position with without priority")
        .withType(Point.Type.PARK_POSITION);
    Point point3 = new Point("another parking position without priority")
        .withType(Point.Type.PARK_POSITION);
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObject(Point.class, point1.getReference())).thenReturn(point1);
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));

    Optional<Point> result = supplier.findParkingPosition(vehicle);
    assertFalse("expected no prioritized parking position to be present", result.isPresent());
  }

  @SuppressWarnings("unchecked")
  private <T> Set<T> setOf(T... resources) {
    return new HashSet<>(Arrays.asList(resources));
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/DriveOrderHistory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.opentcs.guing.model.FigureDecorationDetails;

/**
 * Keeps track of the drive order components of vehicles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DriveOrderHistory {

  /**
   * The drive order components mapped to the vehicle name.
   */
  private final Map<String, Set<FigureDecorationDetails>> driveOrderComponents = new HashMap<>();

  /**
   * Remembers the given set of components as the new drive order components for the given
   * vehicle name and returns the set difference of the old and the new drive order components
   * (e.g. the components that are no longer part of the vehicle's drive order).
   *
   * @param vehicleName The name of the vehicle.
   * @param newDriveOrderComponents The new drive order components.
   * @return The set difference of the old and the new drive order components.
   */
  public Set<FigureDecorationDetails> updateDriveOrderComponents(
      String vehicleName,
      Set<FigureDecorationDetails> newDriveOrderComponents) {
    Set<FigureDecorationDetails> oldDriveOrderComponents
        = getDriveOrderComponents(vehicleName);
    Set<FigureDecorationDetails> finishedDriveOrderComponents
        = new HashSet<>(oldDriveOrderComponents);

    finishedDriveOrderComponents.removeAll(newDriveOrderComponents);

    oldDriveOrderComponents.clear();
    oldDriveOrderComponents.addAll(newDriveOrderComponents);

    return finishedDriveOrderComponents;
  }

  private Set<FigureDecorationDetails> getDriveOrderComponents(String vehicleName) {
    if (!driveOrderComponents.containsKey(vehicleName)) {
      driveOrderComponents.put(vehicleName, new HashSet<>());
    }

    return driveOrderComponents.get(vehicleName);
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v004/VisualLayoutTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v004;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "scaleX", "scaleY", "layers", "layerGroups", "properties"})
public class VisualLayoutTO
    extends PlantModelElementTO {

  private Float scaleX = 0.0F;
  private Float scaleY = 0.0F;
  private List<Layer> layers = new ArrayList<>();
  private List<LayerGroup> layerGroups = new ArrayList<>();

  @XmlAttribute(required = true)
  public Float getScaleX() {
    return scaleX;
  }

  public VisualLayoutTO setScaleX(@Nonnull Float scaleX) {
    requireNonNull(scaleX, "scaleX");
    this.scaleX = scaleX;
    return this;
  }

  @XmlAttribute(required = true)
  public Float getScaleY() {
    return scaleY;
  }

  public VisualLayoutTO setScaleY(@Nonnull Float scaleY) {
    requireNonNull(scaleY, "scaleY");
    this.scaleY = scaleY;
    return this;
  }

  @XmlElement(name = "layer")
  public List<Layer> getLayers() {
    return layers;
  }

  public VisualLayoutTO setLayers(@Nonnull List<Layer> layers) {
    this.layers = requireNonNull(layers, "layers");
    return this;
  }

  @XmlElement(name = "layerGroup")
  public List<LayerGroup> getLayerGroups() {
    return layerGroups;
  }

  public VisualLayoutTO setLayerGroups(@Nonnull List<LayerGroup> layerGroups) {
    this.layerGroups = requireNonNull(layerGroups, "layerGroups");
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"id", "ordinal", "visible", "name", "groupId"})
  public static class Layer {

    private Integer id = 0;
    private Integer ordinal = 0;
    private Boolean visible = true;
    private String name = "";
    private Integer groupId = 0;

    @XmlAttribute(required = true)
    public Integer getId() {
      return id;
    }

    public Layer setId(Integer id) {
      this.id = requireNonNull(id, "id");
      return this;
    }

    @XmlAttribute(required = true)
    public Integer getOrdinal() {
      return ordinal;
    }

    public Layer setOrdinal(Integer ordinal) {
      this.ordinal = requireNonNull(ordinal, "ordinal");
      return this;
    }

    @XmlAttribute(required = true)
    public Boolean isVisible() {
      return visible;
    }

    public Layer setVisible(Boolean visible) {
      this.visible = requireNonNull(visible, "visible");
      return this;
    }

    @XmlAttribute(required = true)
    public String getName() {
      return name;
    }

    public Layer setName(String name) {
      this.name = requireNonNull(name, "name");
      return this;
    }

    @XmlAttribute(required = true)
    public Integer getGroupId() {
      return groupId;
    }

    public Layer setGroupId(Integer groupId) {
      this.groupId = requireNonNull(groupId, "groupId");
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"id", "name", "visible"})
  public static class LayerGroup {

    private Integer id = 0;
    private String name = "";
    private Boolean visible = true;

    @XmlAttribute(required = true)
    public Integer getId() {
      return id;
    }

    public LayerGroup setId(Integer id) {
      this.id = requireNonNull(id, "id");
      return this;
    }

    @XmlAttribute(required = true)
    public String getName() {
      return name;
    }

    public LayerGroup setName(String name) {
      this.name = requireNonNull(name, "name");
      return this;
    }

    @XmlAttribute(required = true)
    public Boolean isVisible() {
      return visible;
    }

    public LayerGroup setVisible(Boolean visible) {
      this.visible = requireNonNull(visible, "visible");
      return this;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/PlantOverviewApplicationConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import java.util.List;
import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;
import org.opentcs.util.gui.dialog.ConnectionParamSet;

/**
 * Provides methods to configure the PlantOverview application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(PlantOverviewApplicationConfiguration.PREFIX)
public interface PlantOverviewApplicationConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "plantoverviewapp";

  @ConfigurationEntry(
      type = "Comma-separated list of <description>\\|<hostname>\\|<port>",
      description = "Kernel connection bookmarks to be used.",
      orderKey = "2_connection_0")
  List<ConnectionParamSet> connectionBookmarks();

  @ConfigurationEntry(
      type = "Boolean",
      description = {
        "Whether to use the configured bookmarks when connecting to the kernel.",
        "If 'true', the first connection bookmark will be used for the connection attempt.",
        "If 'false', a dialog will be shown to enter connection parameters."},
      orderKey = "2_connection_1")
  boolean useBookmarksWhenConnecting();
}


<|start_filename|>openTCS-API-Base/src/test/java/org/opentcs/access/rmi/services/RemoteServicesTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.lang.reflect.Method;
import static java.util.Objects.requireNonNull;
import org.junit.*;
import static org.junit.Assert.fail;
import org.opentcs.access.rmi.ClientID;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.NotificationService;
import org.opentcs.components.kernel.services.PlantModelService;
import org.opentcs.components.kernel.services.RouterService;
import org.opentcs.components.kernel.services.SchedulerService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.components.kernel.services.VehicleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Tests for the remote service interfaces.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RemoteServicesTest {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(RemoteServicesTest.class);

  @Test
  public void shouldMapAllMethodsInServiceInterfaces() {
    checkMapping(DispatcherService.class, RemoteDispatcherService.class);
    checkMapping(NotificationService.class, RemoteNotificationService.class);
    checkMapping(PlantModelService.class, RemotePlantModelService.class);
    checkMapping(RouterService.class, RemoteRouterService.class);
    checkMapping(SchedulerService.class, RemoteSchedulerService.class);
    checkMapping(TCSObjectService.class, RemoteTCSObjectService.class);
    checkMapping(TransportOrderService.class, RemoteTransportOrderService.class);
    checkMapping(VehicleService.class, RemoteVehicleService.class);
  }

  private void checkMapping(Class<?> serviceInterface, Class<?> remoteServiceInterface) {
    for (Method method : serviceInterface.getDeclaredMethods()) {
      try {
        Method remoteMethod = getRemoteServiceMethod(remoteServiceInterface, method);
        LOG.debug("Found {} corresponding to {}", remoteMethod, method);
      }
      catch (NoSuchMethodException exc) {
        fail("Did not find corresponding method for: " + method);
      }
    }
  }

  private static Method getRemoteServiceMethod(Class<?> remoteServiceInterface, Method method)
      throws NoSuchMethodException {
    requireNonNull(method, "method");

    Class<?>[] paramTypes = method.getParameterTypes();
    Class<?>[] extParamTypes = new Class<?>[paramTypes.length + 1];
    // We're looking for a method with the same parameter types as the called one, but with an 
    // additional client ID as the first parameter.
    extParamTypes[0] = ClientID.class;
    System.arraycopy(paramTypes, 0, extParamTypes, 1, paramTypes.length);
    return remoteServiceInterface.getMethod(method.getName(), extParamTypes);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralJobCallback.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import javax.annotation.Nonnull;
import org.opentcs.data.peripherals.PeripheralJob;

/**
 * A callback used to inform about the successful or failed completion of jobs.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralJobCallback {

  /**
   * Called on successful completion of a job.
   *
   * @param job The job that was successfully completed.
   */
  void peripheralJobFinished(@Nonnull PeripheralJob job);

  /**
   * Called on failed completion of a job.
   *
   * @param job The job whose completion has failed.
   */
  void peripheralJobFailed(@Nonnull PeripheralJob job);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayerGroupsPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.TableRowSorter;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.guing.util.IconToolkit;

/**
 * A panel to display and edit layer groups.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerGroupsPanel
    extends JPanel {

  /**
   * The path containing the icons.
   */
  private static final String ICON_PATH = "/org/opentcs/guing/res/symbols/layer/";
  /**
   * The resource bundle to use.
   */
  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewModeling.LAYERS_PATH);
  /**
   * The model manager.
   */
  private final ModelManager modelManager;
  /**
   * The layer manager.
   */
  private final LayerGroupManager layerGroupManager;
  /**
   * The layer editor.
   */
  private final LayerGroupEditorModeling layerGroupEditor;
  /**
   * The table to display available layers.
   */
  private JTable table;
  /**
   * The table model.
   */
  private LayerGroupsTableModel tableModel;

  @Inject
  public LayerGroupsPanel(ModelManager modelManager,
                          LayerGroupManager layerGroupManager,
                          LayerGroupEditorModeling layerGroupEditor) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.layerGroupManager = requireNonNull(layerGroupManager, "layerGroupManager");
    this.layerGroupEditor = requireNonNull(layerGroupEditor, "layerGroupEditor");

    initComponents();
  }

  private void initComponents() {
    setLayout(new BorderLayout());

    tableModel = new LayerGroupsTableModel(modelManager, layerGroupEditor);
    layerGroupManager.addLayerGroupChangeListener(tableModel);
    table = new JTable(tableModel);
    initTable();

    add(createToolBar(), BorderLayout.NORTH);
    add(new JScrollPane(table), BorderLayout.CENTER);
  }

  private void initTable() {
    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    TableRowSorter<LayerGroupsTableModel> sorter = new TableRowSorter<>(tableModel);
    // Sort the table by the layer ordinals...
    sorter.setSortKeys(Arrays.asList(
        new RowSorter.SortKey(LayerGroupsTableModel.COLUMN_ID, SortOrder.DESCENDING)
    ));
    // ...but prevent manual sorting.
    for (int i = 0; i < table.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    table.setRowSorter(sorter);

    // Hide the column that shows the layer group IDs.
    table.removeColumn(table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(LayerGroupsTableModel.COLUMN_ID)));
  }

  private JToolBar createToolBar() {
    JToolBar toolBar = new JToolBar();
    toolBar.setFloatable(false);

    toolBar.add(createAddGroupButton());
    toolBar.add(createRemoveGroupButton());

    return toolBar;
  }

  private JButton createAddGroupButton() {
    IconToolkit iconkit = IconToolkit.instance();
    JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "create-layer-group.16.png"));
    button.addActionListener(actionEvent -> {
      layerGroupEditor.createLayerGroup();
      table.getSelectionModel().setSelectionInterval(0, 0);
    });
    button.setToolTipText(BUNDLE.getString("layerGroupsPanel.button_addGroup.tooltipText"));

    return button;
  }

  private JButton createRemoveGroupButton() {
    IconToolkit iconkit = IconToolkit.instance();
    JButton button = new JButton(iconkit.getImageIconByFullPath(ICON_PATH + "delete-layer-group.16.png"));
    button.addActionListener(new RemoveGroupListener());
    button.setToolTipText(BUNDLE.getString("layerGroupsPanel.button_removeGroup.tooltipText"));

    // Allow the remove group button to be pressed only if there's a group selected and if there's
    // more than one group in the model.
    table.getSelectionModel().addListSelectionListener(listSelectionEvent -> {
      button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
    });
    tableModel.addTableModelListener(tableModelEvent -> {
      button.setEnabled(table.getSelectedRow() != -1 && tableModel.getRowCount() > 1);
    });

    return button;
  }

  private class RemoveGroupListener
      implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
      int selectedRow = table.getSelectedRow();
      int selectedGroupId = tableModel.getDataAt(table.convertRowIndexToModel(selectedRow)).getId();

      Map<Boolean, List<Layer>> layersByGroupAssignment = modelManager.getModel()
          .getLayoutModel().getPropertyLayerWrappers().getValue().values().stream()
          .map(wrapper -> wrapper.getLayer())
          .collect(Collectors.partitioningBy(layer -> layer.getGroupId() == selectedGroupId));
      List<Layer> layersAssignedToGroupToDelete = layersByGroupAssignment.get(Boolean.TRUE);
      List<Layer> layersAssignedToOtherGroups = layersByGroupAssignment.get(Boolean.FALSE);

      if (layersAssignedToOtherGroups.isEmpty()) {
        // All layers in the model are assigned to the group the user wants to remove.
        // In this case, removing the group is not allowed as that would mean that all layers would 
        // be removed as well and there wouldn't be any layers left.
        JOptionPane.showMessageDialog(
            LayerGroupsPanel.this,
            BUNDLE.getString("layerGroupsPanel.optionPane_groupRemovalNotPossible.message"),
            BUNDLE.getString("layerGroupsPanel.optionPane_groupRemovalNotPossible.title"),
            JOptionPane.INFORMATION_MESSAGE
        );
        return;
      }

      if (!layersAssignedToGroupToDelete.isEmpty()) {
        // The user is about remove a group with layers assigned to it. Removing the group results
        // in the assigned layers and the model components they contain to be removed as well.
        int selectedOption = JOptionPane.showConfirmDialog(
            LayerGroupsPanel.this,
            BUNDLE.getString("layerGroupsPanel.optionPane_confirmGroupAndAssignedLayersRemoval.message"),
            BUNDLE.getString("layerGroupsPanel.optionPane_confirmGroupAndAssignedLayersRemoval.title"),
            JOptionPane.YES_NO_OPTION,
            JOptionPane.WARNING_MESSAGE
        );
        if (selectedOption == JOptionPane.NO_OPTION) {
          return;
        }
      }

      layerGroupEditor.deleteLayerGroup(selectedGroupId);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/ObjectPropConstants.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data;

import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.visualization.LocationRepresentation;

/**
 * Defines some reserved/commonly used property keys and values.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ObjectPropConstants {

  /**
   * A property key for models used to store the last-modified time stamp.
   * <p>
   * Type: A time stamp, encoded using ISO 8601. (Can be parsed using {@code java.time.Instant}.)
   * </p>
   */
  String MODEL_FILE_LAST_MODIFIED = "tcs:modelFileLastModified";
  /**
   * A property key for {@link LocationType} instances used to provide a hint for the visualization
   * how locations of the type should be visualized.
   * <p>
   * Type: String (any element of {@link LocationRepresentation})
   * </p>
   */
  String LOCTYPE_DEFAULT_REPRESENTATION = "tcs:defaultLocationTypeSymbol";
  /**
   * A property key for {@link Location} instances used to provide a hint for the visualization how
   * the locations should be visualized.
   * <p>
   * Type: String (any element of {@link LocationRepresentation})
   * </p>
   */
  String LOC_DEFAULT_REPRESENTATION = "tcs:defaultLocationSymbol";
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/PathModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.Arrays;
import java.util.LinkedList;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;
import org.opentcs.data.model.visualization.ElementPropKeys;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.layer.NullLayerWrapper;
import org.opentcs.guing.components.properties.type.BooleanProperty;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.components.properties.type.LayerWrapperProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.properties.type.LinerTypeProperty;
import org.opentcs.guing.components.properties.type.PeripheralOperationsProperty;
import org.opentcs.guing.components.properties.type.SelectionProperty;
import org.opentcs.guing.components.properties.type.SpeedProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.model.FigureDecorationDetails;

/**
 * A connection between two points.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class PathModel
    extends AbstractConnection
    implements FigureDecorationDetails {

  /**
   * Key for the length.
   */
  public static final String LENGTH = "length";
  /**
   * Key for maximum forward velocity.
   */
  public static final String MAX_VELOCITY = "maxVelocity";
  /**
   * Key for maximum reverse velocity.
   */
  public static final String MAX_REVERSE_VELOCITY = "maxReverseVelocity";
  /**
   * Key for the locked state.
   */
  public static final String LOCKED = "locked";
  /**
   * Key for the peripheral operations on this path.
   */
  public static final String PERIPHERAL_OPERATIONS = "peripheralOperations";
  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * The set of vehicle models for which this model component's figure is to be decorated to
   * indicate that it is part of the route of the respective vehicles.
   */
  private Set<VehicleModel> vehicles
      = new TreeSet<>((v1, v2) -> v1.getName().compareTo(v2.getName()));
  /**
   * The set of block models for which this model component's figure is to be decorated to indicate
   * that it is part of the respective block.
   */
  private Set<BlockModel> blocks
      = new TreeSet<>((b1, b2) -> b1.getName().compareTo(b2.getName()));

  /**
   * Creates a new instance.
   */
  public PathModel() {
    createProperties();
  }

  @Override
  public String getDescription() {
    return bundle.getString("pathModel.description");
  }

  public LengthProperty getPropertyLength() {
    return (LengthProperty) getProperty(LENGTH);
  }

  public SpeedProperty getPropertyMaxVelocity() {
    return (SpeedProperty) getProperty(MAX_VELOCITY);
  }

  public SpeedProperty getPropertyMaxReverseVelocity() {
    return (SpeedProperty) getProperty(MAX_REVERSE_VELOCITY);
  }

  public BooleanProperty getPropertyLocked() {
    return (BooleanProperty) getProperty(LOCKED);
  }

  @SuppressWarnings("unchecked")
  public SelectionProperty<Type> getPropertyPathConnType() {
    return (SelectionProperty<Type>) getProperty(ElementPropKeys.PATH_CONN_TYPE);
  }

  public StringProperty getPropertyPathControlPoints() {
    return (StringProperty) getProperty(ElementPropKeys.PATH_CONTROL_POINTS);
  }

  public KeyValueSetProperty getPropertyMiscellaneous() {
    return (KeyValueSetProperty) getProperty(MISCELLANEOUS);
  }

  public PeripheralOperationsProperty getPropertyPeripheralOperations() {
    return (PeripheralOperationsProperty) getProperty(PERIPHERAL_OPERATIONS);
  }

  @Override
  public void addVehicleModel(VehicleModel model) {
    vehicles.add(model);
  }

  @Override
  public void removeVehicleModel(VehicleModel model) {
    vehicles.remove(model);
  }

  @Override
  public Set<VehicleModel> getVehicleModels() {
    return vehicles;
  }

  @Override
  public void addBlockModel(BlockModel model) {
    blocks.add(model);
  }

  @Override
  public void removeBlockModel(BlockModel model) {
    blocks.remove(model);
  }

  @Override
  public Set<BlockModel> getBlockModels() {
    return blocks;
  }

  @Override
  @SuppressWarnings("unchecked")
  public AbstractConnection clone()
      throws CloneNotSupportedException {
    PathModel clone = (PathModel) super.clone();
    clone.setVehicleModels((Set<VehicleModel>) ((TreeSet<VehicleModel>) vehicles).clone());
    clone.setBlockModels((Set<BlockModel>) ((TreeSet<BlockModel>) blocks).clone());

    return clone;
  }

  private void createProperties() {
    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("pathModel.property_name.description"));
    pName.setHelptext(bundle.getString("pathModel.property_name.helptext"));
    setProperty(NAME, pName);

    LengthProperty pLength = new LengthProperty(this);
    pLength.setDescription(bundle.getString("pathModel.property_length.description"));
    pLength.setHelptext(bundle.getString("pathModel.property_length.helptext"));
    setProperty(LENGTH, pLength);

    SpeedProperty pMaxVelocity = new SpeedProperty(this, 1.0, SpeedProperty.Unit.M_S);
    pMaxVelocity.setDescription(bundle.getString("pathModel.property_maximumVelocity.description"));
    pMaxVelocity.setHelptext(bundle.getString("pathModel.property_maximumVelocity.helptext"));
    setProperty(MAX_VELOCITY, pMaxVelocity);

    SpeedProperty pMaxReverseVelocity = new SpeedProperty(this, 0.0, SpeedProperty.Unit.M_S);
    pMaxReverseVelocity.setDescription(bundle.getString("pathModel.property_maximumReverseVelocity.description"));
    pMaxReverseVelocity.setHelptext(bundle.getString("pathModel.property_maximumReverseVelocity.helptext"));
    setProperty(MAX_REVERSE_VELOCITY, pMaxReverseVelocity);

    LinerTypeProperty pPathConnType = new LinerTypeProperty(this, Arrays.asList(Type.values()), Type.values()[0]);
    pPathConnType.setDescription(bundle.getString("pathModel.property_pathConnectionType.description"));
    pPathConnType.setHelptext(bundle.getString("pathModel.property_pathConnectionType.helptext"));
    pPathConnType.setCollectiveEditable(true);
    setProperty(ElementPropKeys.PATH_CONN_TYPE, pPathConnType);

    StringProperty pPathControlPoints = new StringProperty(this);
    pPathControlPoints.setDescription(bundle.getString("pathModel.property_pathControlPoints.description"));
    pPathControlPoints.setHelptext(bundle.getString("pathModel.property_pathControlPoints.helptext"));
    // Control points may only be moved in the drawing.
    pPathControlPoints.setModellingEditable(false);
    setProperty(ElementPropKeys.PATH_CONTROL_POINTS, pPathControlPoints);

    StringProperty startComponent = new StringProperty(this);
    startComponent.setDescription(bundle.getString("pathModel.property_startComponent.description"));
    startComponent.setModellingEditable(false);
    startComponent.setOperatingEditable(false);
    setProperty(START_COMPONENT, startComponent);
    StringProperty endComponent = new StringProperty(this);
    endComponent.setDescription(bundle.getString("pathModel.property_endComponent.description"));
    endComponent.setModellingEditable(false);
    endComponent.setOperatingEditable(false);
    setProperty(END_COMPONENT, endComponent);

    LayerWrapperProperty pLayerWrapper = new LayerWrapperProperty(this, new NullLayerWrapper());
    pLayerWrapper.setDescription(bundle.getString("pathModel.property_layerWrapper.description"));
    pLayerWrapper.setHelptext(bundle.getString("pathModel.property_layerWrapper.helptext"));
    pLayerWrapper.setModellingEditable(false);
    setProperty(LAYER_WRAPPER, pLayerWrapper);

    BooleanProperty pLocked = new BooleanProperty(this);
    pLocked.setDescription(bundle.getString("pathModel.property_locked.description"));
    pLocked.setHelptext(bundle.getString("pathModel.property_locked.helptext"));
    pLocked.setCollectiveEditable(true);
    pLocked.setOperatingEditable(true);
    setProperty(LOCKED, pLocked);

    PeripheralOperationsProperty pOperations = new PeripheralOperationsProperty(this, new LinkedList<>());
    pOperations.setDescription(bundle.getString("pathModel.property_peripheralOperations.description"));
    pOperations.setHelptext(bundle.getString("pathModel.property_peripheralOperations.helptext"));
    setProperty(PERIPHERAL_OPERATIONS, pOperations);

    KeyValueSetProperty pMiscellaneous = new KeyValueSetProperty(this);
    pMiscellaneous.setDescription(bundle.getString("pathModel.property_miscellaneous.description"));
    pMiscellaneous.setHelptext(bundle.getString("pathModel.property_miscellaneous.helptext"));
    pMiscellaneous.setOperatingEditable(true);
    setProperty(MISCELLANEOUS, pMiscellaneous);
  }

  private void setVehicleModels(Set<VehicleModel> vehicles) {
    this.vehicles = vehicles;
  }

  private void setBlockModels(Set<BlockModel> blocks) {
    this.blocks = blocks;
  }

  /**
   * The supported liner types for connections.
   */
  public enum Type {

    /**
     * A direct connection.
     */
    DIRECT(ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.direct.description"),
           ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.direct.helptext")),
    /**
     * An elbow connection.
     */
    ELBOW(ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.elbow.description"),
          ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.elbow.helptext")),
    /**
     * A slanted connection.
     */
    SLANTED(ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.slanted.description"),
            ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.slanted.helptext")),
    /**
     * A polygon path with any number of vertecies.
     */
    POLYPATH(ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.polypath.description"),
             ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.polypath.helptext")),

    /**
     * A bezier curve with 2 control points.
     */
    BEZIER(ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.bezier.description"),
           ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.bezier.helptext")),
    /**
     * A bezier curve with 3 control points.
     */
    BEZIER_3(ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.bezier3.description"),
             ResourceBundle.getBundle(BUNDLE_PATH).getString("pathModel.type.bezier3.helptext"));

    private final String description;

    private final String helptext;

    private Type(String description, String helptext) {
      this.description = requireNonNull(description, "description");
      this.helptext = requireNonNull(helptext, "helptext");
    }

    public String getDescription() {
      return description;
    }

    public String getHelptext() {
      return helptext;
    }

    /**
     * Returns the <code>Type</code> constant matching the name in the
     * given input. This method permits extraneous whitespace around the name
     * and is case insensitive, which makes it a bit more liberal than the
     * default <code>valueOf</code> that all enums provide.
     *
     * @param input The name of the enum constant to return.
     * @return The enum constant matching the given name.
     * @throws IllegalArgumentException If this enum has no constant with the
     * given name.
     */
    public static Type valueOfNormalized(String input)
        throws IllegalArgumentException {
      String normalizedInput = requireNonNull(input, "input is null").trim();

      for (Type curType : values()) {
        if (normalizedInput.equalsIgnoreCase(curType.name())) {
          return curType;
        }
      }

      throw new IllegalArgumentException("No match for '" + input + "'");
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/dialogs/FindVehiclePanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dialogs;

import java.util.Collection;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface FindVehiclePanelFactory {

  /**
   * Create a {@link FindVehiclePanel} for the given vehicle models.
   *
   * @param vehicles The vehicle models.
   * @param drawingView The drawing view.
   * @return A {@link FindVehiclePanel}.
   */
  FindVehiclePanel createFindVehiclesPanel(Collection<VehicleModel> vehicles,
                                           OpenTCSDrawingView drawingView);
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/NullPeripheralCommAdapterFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import org.opentcs.common.peripherals.NullPeripheralCommAdapterDescription;
import org.opentcs.data.model.Location;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterFactory;

/**
 * A factory for {@link NullPeripheralCommAdapter}s.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullPeripheralCommAdapterFactory
    implements PeripheralCommAdapterFactory {

  /**
   * Creates a new NullPeripheralCommAdapterFactory.
   */
  public NullPeripheralCommAdapterFactory() {
  }

  @Override
  public PeripheralCommAdapterDescription getDescription() {
    return new NullPeripheralCommAdapterDescription();
  }

  @Override
  public boolean providesAdapterFor(Location location) {
    return true;
  }

  @Override
  public PeripheralCommAdapter getAdapterFor(Location location) {
    return new NullPeripheralCommAdapter(location.getReference());
  }

  @Override
  public void initialize() {
  }

  @Override
  public boolean isInitialized() {
    return true;
  }

  @Override
  public void terminate() {
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LocationProperties.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LocationProperties {

  /**
   * The key of the location property indicating that the location represents a peripheral device
   * and that it should be attached to the loopback peripheral communication adapter.
   */
  String PROPKEY_LOOPBACK_PERIPHERAL = "tcs:loopbackPeripheral";
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/SchedulerService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.SchedulerAllocationState;
import org.opentcs.components.kernel.Scheduler;

/**
 * Provides methods concerning the {@link Scheduler}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface SchedulerService {

  /**
   * Returns the current state of resource allocations.
   *
   * @return The current state of resource allocations.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  SchedulerAllocationState fetchSchedulerAllocations()
      throws KernelRuntimeException;
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/guiceConfig/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralControlCenterModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import com.google.inject.assistedinject.FactoryModuleBuilder;
import org.opentcs.customizations.controlcenter.ControlCenterInjectionModule;

/**
 * Loopback adapter-specific Gucie configuration for the Kernel Control Center.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralControlCenterModule
    extends ControlCenterInjectionModule {

  @Override
  protected void configure() {
    install(new FactoryModuleBuilder().build(LoopbackPeripheralAdapterPanelComponentsFactory.class));

    peripheralCommAdapterPanelFactoryBinder()
        .addBinding().to(LoopbackPeripheralCommAdapterPanelFactory.class);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/CoordinateUndoActivity.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import com.google.inject.assistedinject.Assisted;
import java.awt.geom.AffineTransform;
import static java.util.Objects.requireNonNull;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.properties.event.NullAttributesChangeListener;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.PositionableModelComponent;
import org.opentcs.guing.persistence.ModelManager;

/**
 * An undo for the modification of a coordinate property.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class CoordinateUndoActivity
    extends AbstractUndoableEdit {

  protected final CoordinateProperty property;
  protected final CoordinateProperty pxModel;
  protected final CoordinateProperty pyModel;
  protected final LabeledFigure bufferedFigure;
  protected final AffineTransform bufferedTransform = new AffineTransform();
  private CoordinateProperty pxBeforeModification;
  private CoordinateProperty pyBeforeModification;
  private CoordinateProperty pxAfterModification;
  private CoordinateProperty pyAfterModification;

  /**
   * Creates a new instance.
   *
   * @param property The affected property.
   * @param modelManager The model manager to be used.
   */
  public CoordinateUndoActivity(@Assisted CoordinateProperty property,
                                ModelManager modelManager) {
    this.property = requireNonNull(property, "property");

    ModelComponent model = property.getModel();
    pxModel = (CoordinateProperty) model.getProperty(PositionableModelComponent.MODEL_X_POSITION);
    pyModel = (CoordinateProperty) model.getProperty(PositionableModelComponent.MODEL_Y_POSITION);
    bufferedFigure = (LabeledFigure) modelManager.getModel().getFigure(model);
  }

  /**
   * Creates a snapshot before the modification of the properties.
   */
  public void snapShotBeforeModification() {
    pxBeforeModification = (CoordinateProperty) pxModel.clone();
    pyBeforeModification = (CoordinateProperty) pyModel.clone();

    saveTransformBeforeModification();
  }

  /**
   * Creates a snapshot after the modification of the properties.
   */
  public void snapShotAfterModification() {
    pxAfterModification = (CoordinateProperty) pxModel.clone();
    pyAfterModification = (CoordinateProperty) pyModel.clone();
  }

  @Override
  public void undo()
      throws CannotUndoException {
    super.undo();

    pxModel.copyFrom(pxBeforeModification);
    pyModel.copyFrom(pyBeforeModification);
    pxModel.markChanged();
    pyModel.markChanged();

    saveTransformForUndo();

    pxModel.getModel().propertiesChanged(new NullAttributesChangeListener());
  }

  @Override
  public void redo()
      throws CannotRedoException {
    super.redo();

    pxModel.copyFrom(pxAfterModification);
    pyModel.copyFrom(pyAfterModification);
    pxModel.markChanged();
    pyModel.markChanged();

    saveTransformForRedo();

    pxModel.getModel().propertiesChanged(new NullAttributesChangeListener());
  }

  protected abstract void saveTransformBeforeModification();

  protected abstract void saveTransformForUndo();

  protected abstract void saveTransformForRedo();
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/action/file/DownloadModelFromKernelAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.file;

import java.awt.event.ActionEvent;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.AbstractAction;
import static javax.swing.Action.ACCELERATOR_KEY;
import static javax.swing.Action.MNEMONIC_KEY;
import javax.swing.KeyStroke;
import org.opentcs.guing.application.OpenTCSView;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.MENU_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * An action to load the current kernel model in the plant overview.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DownloadModelFromKernelAction
    extends AbstractAction {

  public static final String ID = "file.downloadModelFromKernel";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
  /**
   * The OpenTCS view.
   */
  private final OpenTCSView openTCSView;

  /**
   * Creates a new instance.
   *
   * @param openTCSView The openTCS view.
   */
  @Inject
  public DownloadModelFromKernelAction(OpenTCSView openTCSView) {
    this.openTCSView = requireNonNull(openTCSView);

    putValue(NAME, BUNDLE.getString("downloadModelFromKernelAction.name"));
    putValue(SHORT_DESCRIPTION, BUNDLE.getString("downloadModelFromKernelAction.shortDescription"));
    putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt K"));
    putValue(MNEMONIC_KEY, Integer.valueOf('K'));
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    openTCSView.downloadModelFromKernel();
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/edgeevaluator/ExplicitPropertiesConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing.edgeevaluator;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure {@link EdgeEvaluatorExplicitProperties}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(ExplicitPropertiesConfiguration.PREFIX)
public interface ExplicitPropertiesConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "defaultrouter.edgeevaluator.explicitproperties";

  @ConfigurationEntry(
      type = "String",
      description = {
        "The default value used as the routing cost of an edge if no property is set on the "
        + "corresponding path.",
        "The value should be an integer. "
        + "If it is not, the edge is excluded from routing."})
  String defaultValue();
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralAdapterCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import java.io.Serializable;
import javax.annotation.Nonnull;

/**
 * A command a peripheral communication adapter may execute.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralAdapterCommand
    extends Serializable {

  /**
   * Executes the command.
   *
   * @param adapter The communication adapter to execute the command with.
   */
  void execute(@Nonnull PeripheralCommAdapter adapter);
}


<|start_filename|>openTCS-OperationsDesk/src/guiceConfig/java/org/opentcs/guing/DefaultImportersExportersModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing;

import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;

/**
 * Configures/binds the default importers and exporters of the openTCS plant overview.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultImportersExportersModule
    extends PlantOverviewInjectionModule {

  @Override
  protected void configure() {
    plantModelImporterBinder();
    plantModelExporterBinder();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/Location.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.Nonnull;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.visualization.LocationRepresentation;

/**
 * A location at which a {@link Vehicle} may perform an action.
 * <p>
 * A location must be linked to at least one {@link Point} to be reachable for a vehicle.
 * It may be linked to multiple points.
 * As long as a link's specific set of allowed operations is empty (which is the default), all
 * operations defined by the location's referenced {@link LocationType} are allowed at the linked
 * point.
 * If the link's set of allowed operations is not empty, only the operations contained in it are
 * allowed at the linked point.
 * </p>
 *
 * @see LocationType
 * @author <NAME> (Fraunhofer IML)
 */
public class Location
    extends TCSResource<Location>
    implements Serializable {

  /**
   * This location's position in mm.
   */
  private final Triple position;
  /**
   * A reference to this location's type.
   */
  private final TCSObjectReference<LocationType> type;
  /**
   * A set of links attached to this location.
   */
  private final Set<Link> attachedLinks;
  /**
   * A flag for marking this location as locked (i.e. to prevent transport orders leading to it
   * from being assigned to vehicles).
   */
  private final boolean locked;
  /**
   * Details about the peripheral devices this location may represent.
   */
  private final PeripheralInformation peripheralInformation;
  /**
   * The information regarding the grahical representation of this location.
   */
  private final Layout layout;

  /**
   * Creates a new Location.
   *
   * this.locked = false;
   *
   * @param name The new location's name.
   * @param type The new location's type.
   */
  public Location(String name, TCSObjectReference<LocationType> type) {
    super(name);
    this.type = requireNonNull(type, "type");
    this.position = new Triple(0, 0, 0);
    this.attachedLinks = new HashSet<>();
    this.locked = false;
    this.peripheralInformation = new PeripheralInformation();
    this.layout = new Layout();
  }

  private Location(String name,
                   Map<String, String> properties,
                   ObjectHistory history,
                   TCSObjectReference<LocationType> locationType,
                   Triple position,
                   Set<Link> attachedLinks,
                   boolean locked,
                   PeripheralInformation peripheralInformation,
                   Layout layout) {
    super(name, properties, history);
    this.type = requireNonNull(locationType, "locationType");
    this.position = requireNonNull(position, "position");
    this.attachedLinks = new HashSet<>(requireNonNull(attachedLinks, "attachedLinks"));
    this.locked = locked;
    this.peripheralInformation = requireNonNull(peripheralInformation, "peripheralInformation");
    this.layout = requireNonNull(layout, "layout");
  }

  @Override
  public Location withProperty(String key, String value) {
    return new Location(getName(),
                        propertiesWith(key, value),
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  @Override
  public Location withProperties(Map<String, String> properties) {
    return new Location(getName(),
                        properties,
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  @Override
  public TCSObject<Location> withHistoryEntry(ObjectHistory.Entry entry) {
    return new Location(getName(),
                        getProperties(),
                        getHistory().withEntryAppended(entry),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  @Override
  public TCSObject<Location> withHistory(ObjectHistory history) {
    return new Location(getName(),
                        getProperties(),
                        history,
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  /**
   * Returns the physical coordinates of this location in mm.
   *
   * @return The physical coordinates of this location in mm.
   */
  public Triple getPosition() {
    return position;
  }

  /**
   * Creates a copy of this object, with the given position.
   *
   * @param position The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Location withPosition(Triple position) {
    return new Location(getName(),
                        getProperties(),
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  /**
   * Returns a reference to the type of this location.
   *
   * @return A reference to the type of this location.
   */
  public TCSObjectReference<LocationType> getType() {
    return type;
  }

  /**
   * Returns a set of links attached to this location.
   *
   * @return A set of links attached to this location.
   */
  public Set<Link> getAttachedLinks() {
    return Collections.unmodifiableSet(attachedLinks);
  }

  /**
   * Creates a copy of this object, with the given attached links.
   *
   * @param attachedLinks The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Location withAttachedLinks(@Nonnull Set<Link> attachedLinks) {
    return new Location(getName(),
                        getProperties(),
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  /**
   * Returns details about the peripheral devices this location may represent.
   *
   * @return Details about the peripheral devices this location may represent.
   */
  @Nonnull
  public PeripheralInformation getPeripheralInformation() {
    return peripheralInformation;
  }

  /**
   * Creates a copy of this object, with the given peripheral information.
   *
   * @param peripheralInformation The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Location withPeripheralInformation(@Nonnull PeripheralInformation peripheralInformation) {
    return new Location(getName(),
                        getProperties(),
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  /**
   * Returns the lock status of this location (i.e. whether it my be used by vehicles or not).
   *
   * @return {@code true} if this location is currently locked (i.e. it may not be used
   * by vehicles), else {@code false}.
   */
  public boolean isLocked() {
    return locked;
  }

  /**
   * Creates a copy of this object, with the given locked flag.
   *
   * @param locked The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Location withLocked(boolean locked) {
    return new Location(getName(),
                        getProperties(),
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  /**
   * Returns the information regarding the grahical representation of this location.
   *
   * @return The information regarding the grahical representation of this location.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public Location withLayout(Layout layout) {
    return new Location(getName(),
                        getProperties(),
                        getHistory(),
                        type,
                        position,
                        attachedLinks,
                        locked,
                        peripheralInformation,
                        layout);
  }

  /**
   * A link connecting a point and a location, expressing that the location is
   * reachable from the point.
   */
  public static class Link
      implements Serializable {

    /**
     * A reference to the location end of this link.
     */
    private final TCSResourceReference<Location> location;
    /**
     * A reference to the point end of this link.
     */
    private final TCSResourceReference<Point> point;
    /**
     * The operations allowed at this link.
     */
    private final Set<String> allowedOperations;

    /**
     * Creates a new Link.
     *
     * @param location A reference to the location end of this link.
     * @param point A reference to the point end of this link.
     */
    public Link(TCSResourceReference<Location> location,
                TCSResourceReference<Point> point) {
      this.location = requireNonNull(location, "location");
      this.point = requireNonNull(point, "point");
      this.allowedOperations = new TreeSet<>();
    }

    private Link(TCSResourceReference<Location> location,
                 TCSResourceReference<Point> point,
                 Set<String> allowedOperations) {
      this.location = requireNonNull(location, "location");
      this.point = requireNonNull(point, "point");
      this.allowedOperations = new TreeSet<>(requireNonNull(allowedOperations,
                                                            "allowedOperations"));
    }

    /**
     * Returns a reference to the location end of this link.
     *
     * @return A reference to the location end of this link.
     */
    public TCSResourceReference<Location> getLocation() {
      return location;
    }

    /**
     * Returns a reference to the point end of this link.
     *
     * @return A reference to the point end of this link.
     */
    public TCSResourceReference<Point> getPoint() {
      return point;
    }

    /**
     * Returns the operations allowed at this link.
     *
     * @return The operations allowed at this link.
     */
    public Set<String> getAllowedOperations() {
      return Collections.unmodifiableSet(allowedOperations);
    }

    /**
     * Checks if a vehicle is allowed to execute a given operation at this link.
     *
     * @param operation The operation to be checked.
     * @return <code>true</code> if, and only if, vehicles are allowed to
     * execute the given operation at his link.
     */
    public boolean hasAllowedOperation(String operation) {
      requireNonNull(operation, "operation");
      return allowedOperations.contains(operation);
    }

    /**
     * Creates a copy of this object, with the given allowed operations.
     *
     * @param allowedOperations The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Link withAllowedOperations(Set<String> allowedOperations) {
      return new Link(location, point, allowedOperations);
    }

    /**
     * Checks if this object is equal to another one.
     * Two <code>Link</code>s are equal if they both reference the same location
     * and point ends.
     *
     * @param obj The object to compare this one to.
     * @return <code>true</code> if, and only if, <code>obj</code> is also a
     * <code>Link</code> and reference the same location and point ends as this
     * one.
     */
    @Override
    public boolean equals(Object obj) {
      if (obj instanceof Link) {
        Link other = (Link) obj;
        return point.equals(other.getPoint())
            && location.equals(other.getLocation());
      }
      else {
        return false;
      }
    }

    /**
     * Returns a hash code for this link.
     * The hash code of a <code>Location.Link</code> is computed as the
     * exclusive OR (XOR) of the hash codes of the associated location and point
     * references.
     *
     * @return A hash code for this link.
     */
    @Override
    public int hashCode() {
      return location.hashCode() ^ point.hashCode();
    }
  }

  /**
   * Contains information regarding the grahical representation of a location.
   */
  public static class Layout
      implements Serializable {

    /**
     * The coordinates at which the location is to be drawn (in mm).
     */
    private final Couple position;
    /**
     * The offset of the label's position to the location's position (in lu).
     */
    private final Couple labelOffset;
    /**
     * The location representation to use.
     */
    private final LocationRepresentation locationRepresentation;
    /**
     * The ID of the layer on which the location is to be drawn.
     */
    private final int layerId;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(new Couple(0, 0), new Couple(0, 0), LocationRepresentation.DEFAULT, 0);
    }

    /**
     * Creates a new instance.
     *
     * @param position The coordinates at which the location is to be drawn (in mm).
     * @param labelOffset The offset of the label's location to the point's position (in lu).
     * @param locationRepresentation The location representation to use.
     * @param layerId The ID of the layer on which the location is to be drawn.
     */
    public Layout(Couple position,
                  Couple labelOffset,
                  LocationRepresentation locationRepresentation,
                  int layerId) {
      this.position = requireNonNull(position, "position");
      this.labelOffset = requireNonNull(labelOffset, "labelOffset");
      this.locationRepresentation = requireNonNull(locationRepresentation,
                                                   "locationRepresentation");
      this.layerId = layerId;
    }

    /**
     * Returns the coordinates at which the location is to be drawn (in mm).
     *
     * @return The coordinates at which the location is to be drawn (in mm).
     */
    public Couple getPosition() {
      return position;
    }

    /**
     * Creates a copy of this object, with the given position.
     *
     * @param position The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withPosition(Couple position) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    /**
     * Returns the offset of the label's position to the location's position (in lu).
     *
     * @return The offset of the label's position to the location's position (in lu).
     */
    public Couple getLabelOffset() {
      return labelOffset;
    }

    /**
     * Creates a copy of this object, with the given X label offset.
     *
     * @param labelOffset The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLabelOffset(Couple labelOffset) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    /**
     * Returns the location representation to use.
     *
     * @return The location representation to use.
     */
    public LocationRepresentation getLocationRepresentation() {
      return locationRepresentation;
    }

    /**
     * Creates a copy of this object, with the given location representation.
     *
     * @param locationRepresentation The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLocationRepresentation(LocationRepresentation locationRepresentation) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    /**
     * Returns the ID of the layer on which the location is to be drawn.
     *
     * @return The layer ID.
     */
    public int getLayerId() {
      return layerId;
    }

    /**
     * Creates a copy of this object, with the given layer ID.
     *
     * @param layerId The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLayerId(int layerId) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/ComponentContext.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.inject.Inject;
import javax.swing.JPopupMenu;
import org.opentcs.guing.application.GuiManager;

/**
 * Context for the component tree view.
 *
 * @author <NAME> (<EMAIL>)
 */
public class ComponentContext
    implements UserObjectContext {

  private final GuiManager guiManager;

  /**
   * Creates a new instance.
   *
   * @param guiManager The gui manager.
   */
  @Inject
  public ComponentContext(GuiManager guiManager) {
    this.guiManager = requireNonNull(guiManager, "guiManager");
  }

  @Override
  public JPopupMenu getPopupMenu(final Set<UserObject> selectedUserObjects) {
    JPopupMenu menu = new JPopupMenu();
    return menu;
  }

  @Override
  public boolean removed(UserObject userObject) {
    return guiManager.treeComponentRemoved(userObject.getModelComponent());
  }

  @Override
  public ContextType getType() {
    return ContextType.COMPONENT;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/AttributesContent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import javax.swing.JComponent;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;

/**
 * Interface for Swing components that allow editing and viewing a model component attribute.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface AttributesContent {

  /**
   * Sets the model component whose properties are to be displayed.
   *
   * @param model The model component whose properties are to be displayed.
   */
  void setModel(ModelComponent model);

  /**
   * Resets this content to no longer display the model component properties.
   */
  void reset();

  /**
   * Returns the content as a Swing component.
   *
   * @return The content as a Swing component.
   */
  JComponent getComponent();

  /**
   * Return a description of the content.
   *
   * @return A description of the content.
   */
  String getDescription();

  /**
   * Initialises the content with the undo manager.
   *
   * @param undoRedoManager The content with the undo manager.
   */
  void setup(UndoRedoManager undoRedoManager);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/edit/ClearSelectionAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.action.edit;

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import static javax.swing.Action.ACCELERATOR_KEY;
import static javax.swing.Action.LARGE_ICON_KEY;
import static javax.swing.Action.SMALL_ICON;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.text.JTextComponent;
import org.opentcs.guing.components.EditableComponent;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.MENU_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Clears (de-selects) the selected region.
 * This action acts on the last {@code JTextComponent} which had the focus
 * when the {@code ActionEvent} was generated.
 * This action is called when the user selects the "Clear Selection" item
 * in the Edit menu. The menu item is automatically created by the application.
 *
 * @author <NAME>.
 */
public class ClearSelectionAction
    extends org.jhotdraw.app.action.edit.AbstractSelectionAction {

  public final static String ID = "edit.clearSelection";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);

  /**
   * Creates a new instance which acts on the currently focused component.
   */
  public ClearSelectionAction() {
    this(null);
  }

  /**
   * Creates a new instance which acts on the specified component.
   *
   * @param target The target of the action. Specify null for the currently
   * focused component.
   */
  public ClearSelectionAction(JComponent target) {
    super(target);

    putValue(NAME, BUNDLE.getString("clearSelectionAction.name"));
    putValue(SHORT_DESCRIPTION, BUNDLE.getString("clearSelectionAction.shortDescription"));
    putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("shift ctrl A"));

    ImageIcon icon = ImageDirectory.getImageIcon("/menu/edit-clear-2.png");
    putValue(SMALL_ICON, icon);
    putValue(LARGE_ICON_KEY, icon);
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    JComponent cTarget = target;
    Component cFocusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();

    if (cTarget == null && (cFocusOwner instanceof JComponent)) {
      cTarget = (JComponent) cFocusOwner;
    }

    if (cTarget != null && cTarget.isEnabled()) {
      if (cTarget instanceof EditableComponent) {
        ((EditableComponent) cTarget).clearSelection();
      }
      else if (cTarget instanceof JTextComponent) {
        JTextComponent tc = ((JTextComponent) cTarget);
        tc.select(tc.getSelectionStart(), tc.getSelectionStart());
      }
      else {
        cTarget.getToolkit().beep();
      }
    }
  }

  @Override
  protected void updateEnabled() {
    if (target != null) {
      setEnabled(target.isEnabled());
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/orders/ContainsLockedTargetLocations.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.orders;

import com.google.common.base.Objects;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.selection.TransportOrderSelectionFilter;

/**
 * Filters transport orders that contain locked target locations.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ContainsLockedTargetLocations
    implements TransportOrderSelectionFilter {

  /**
   * The object service.
   */
  private final TCSObjectService objectService;

  @Inject
  public ContainsLockedTargetLocations(TCSObjectService objectService) {
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public Collection<String> apply(TransportOrder order) {
    return !lockedLocations(order) ? new ArrayList<>() : Arrays.asList(getClass().getName());
  }

  @SuppressWarnings("unchecked")
  private boolean lockedLocations(TransportOrder order) {
    return order.getAllDriveOrders().stream()
        .map(driveOrder -> driveOrder.getDestination().getDestination())
        .filter(destination -> Objects.equal(destination.getReferentClass(), Location.class))
        .map(destination -> (TCSObjectReference<Location>) destination)
        .map(locationReference -> objectService.fetchObject(Location.class, locationReference))
        .anyMatch(location -> location.isLocked());
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralCommAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.util.ExplainedBoolean;

/**
 * This interface declares the methods that a driver communicating with and controlling a
 * peripheral device must implement.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralCommAdapter
    extends Lifecycle {

  /**
   * Enables this comm adapter, i.e. turns it on.
   */
  void enable();

  /**
   * Disables this comm adapter, i.e. turns it off.
   */
  void disable();

  /**
   * Checks whether this communication adapter is enabled.
   *
   * @return {@code true} if, and only if, this communication adapter is enabled.
   */
  boolean isEnabled();

  /**
   * Returns a model of the peripheral device's and its communication adapter's attributes.
   *
   * @return A model of the peripheral device's and its communication adapter's attributes.
   */
  @Nonnull
  PeripheralProcessModel getProcessModel();

  /**
   * Checks if the peripheral device would be able to process the given job, taking into account
   * its current state.
   *
   * @param job A job that might have to be processed.
   * @return An {@link ExplainedBoolean} telling if the peripheral device would be able to process
   * the job.
   */
  @Nonnull
  ExplainedBoolean canProcess(@Nonnull PeripheralJob job);

  /**
   * Processes the given job by sending it or a representation that the peripheral device
   * understands to the peripheral device itself. The callback is used to inform about the
   * successful or failed completion of the job.
   *
   * @param job The job to process.
   * @param callback The callback to use.
   */
  void process(@Nonnull PeripheralJob job, @Nonnull PeripheralJobCallback callback);

  /**
   * Executes the given {@link PeripheralAdapterCommand}.
   *
   * @param command The command to execute.
   */
  void execute(@Nonnull PeripheralAdapterCommand command);
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralProcessModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import java.io.Serializable;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;

/**
 * The process model for the loopback peripheral communication adapter.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralProcessModel
    extends PeripheralProcessModel
    implements Serializable {

  /**
   * Whether the peripheral device is manual mode (i.e. the user triggers the job execution).
   */
  private final boolean manualModeEnabled;
  /**
   * Whether the peripheral device is paused or not.
   */
  private final boolean peripheralPaused;

  public LoopbackPeripheralProcessModel(TCSResourceReference<Location> location) {
    this(location, false, false, PeripheralInformation.State.UNKNOWN, false, false);
  }

  private LoopbackPeripheralProcessModel(TCSResourceReference<Location> location,
                                         boolean commAdapterEnabled,
                                         boolean commAdapterConnected,
                                         PeripheralInformation.State state,
                                         boolean manualModeEnabled,
                                         boolean peripheralPaused) {
    super(location, commAdapterEnabled, commAdapterConnected, state);
    this.manualModeEnabled = manualModeEnabled;
    this.peripheralPaused = peripheralPaused;
  }

  @Override
  public LoopbackPeripheralProcessModel withLocation(TCSResourceReference<Location> location) {
    return new LoopbackPeripheralProcessModel(location,
                                              isCommAdapterEnabled(),
                                              isCommAdapterConnected(),
                                              getState(),
                                              manualModeEnabled,
                                              peripheralPaused);
  }

  @Override
  public LoopbackPeripheralProcessModel withCommAdapterEnabled(boolean commAdapterEnabled) {
    return new LoopbackPeripheralProcessModel(getLocation(),
                                              commAdapterEnabled,
                                              isCommAdapterConnected(),
                                              getState(),
                                              manualModeEnabled,
                                              peripheralPaused);
  }

  @Override
  public LoopbackPeripheralProcessModel withCommAdapterConnected(boolean commAdapterConnected) {
    return new LoopbackPeripheralProcessModel(getLocation(),
                                              isCommAdapterEnabled(),
                                              commAdapterConnected,
                                              getState(),
                                              manualModeEnabled,
                                              peripheralPaused);
  }

  @Override
  public LoopbackPeripheralProcessModel withState(PeripheralInformation.State state) {
    return new LoopbackPeripheralProcessModel(getLocation(),
                                              isCommAdapterEnabled(),
                                              isCommAdapterConnected(),
                                              state,
                                              manualModeEnabled,
                                              peripheralPaused);
  }

  /**
   * Returns whether the peripheral device is manual mode (i.e. the user triggers the job
   * execution).
   *
   * @return Whether the peripheral device is manual mode.
   */
  public boolean isManualModeEnabled() {
    return manualModeEnabled;
  }

  /**
   * Creates a copy of the object, with the given value.
   *
   * @param manualModeEnabled The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LoopbackPeripheralProcessModel withManualModeEnabled(boolean manualModeEnabled) {
    return new LoopbackPeripheralProcessModel(getLocation(),
                                              isCommAdapterEnabled(),
                                              isCommAdapterConnected(),
                                              getState(),
                                              manualModeEnabled,
                                              peripheralPaused);
  }

  /**
   * Returns whether the peripheral device is paused or not.
   *
   * @return Whether the peripheral device is paused or not.
   */
  public boolean isPeripheralPaused() {
    return peripheralPaused;
  }

  /**
   * Creates a copy of the object, with the given value.
   *
   * @param peripheralPaused The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LoopbackPeripheralProcessModel withPeripheralPaused(boolean peripheralPaused) {
    return new LoopbackPeripheralProcessModel(getLocation(),
                                              isCommAdapterEnabled(),
                                              isCommAdapterConnected(),
                                              getState(),
                                              manualModeEnabled,
                                              peripheralPaused);
  }

  /**
   * Used to describe what has changed in a process model.
   */
  public enum Attribute {
    /**
     * Indicates a change of the manual mode enabled property.
     */
    MANUAL_MODE_ENABLED,
    /**
     * Indicates a change of the peripheral paused property.
     */
    PERIPHERAL_PAUSED;
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/model/CachedSystemModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model;

import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.util.ModelComponentFactory;

/**
 * Extends the standard system model with a cache of model components
 * to provide a more efficient lookup of components by name.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CachedSystemModel
    extends StandardSystemModel {

  /**
   * A map from component name to the actual component.
   */
  private final Map<String, ModelComponent> components = new HashMap<>();

  @Inject
  public CachedSystemModel(ModelComponentFactory modelComponentFactory) {
    super(modelComponentFactory);
  }

  @Override
  public void onRestorationComplete() {
    components.clear();
    for (ModelComponent component : getAll()) {
      components.put(component.getName(), component);
    }
  }

  @Override
  public BlockModel getBlockModel(String name) {
    if (components.isEmpty()) {
      return super.getBlockModel(name);
    }

    ModelComponent block = components.get(name);
    if (block instanceof BlockModel) {
      return (BlockModel) block;
    }
    return null;
  }

  @Override
  public LocationModel getLocationModel(String name) {
    if (components.isEmpty()) {
      return super.getLocationModel(name);
    }

    ModelComponent location = components.get(name);
    if (location instanceof LocationModel) {
      return (LocationModel) location;
    }
    return null;
  }

  @Override
  public LocationTypeModel getLocationTypeModel(String name) {
    if (components.isEmpty()) {
      return super.getLocationTypeModel(name);
    }

    ModelComponent locationType = components.get(name);
    if (locationType instanceof LocationTypeModel) {
      return (LocationTypeModel) locationType;
    }
    return null;
  }

  @Override
  public ModelComponent getModelComponent(String name) {
    if (components.isEmpty()) {
      return super.getModelComponent(name);
    }
    return components.get(name);
  }

  @Override
  public PathModel getPathModel(String name) {
    if (components.isEmpty()) {
      return super.getPathModel(name);
    }

    ModelComponent path = components.get(name);
    if (path instanceof PathModel) {
      return (PathModel) path;
    }
    return null;
  }

  @Override
  public PointModel getPointModel(String name) {
    if (components.isEmpty()) {
      return super.getPointModel(name);
    }

    ModelComponent point = components.get(name);
    if (point instanceof PointModel) {
      return (PointModel) point;
    }
    return null;
  }

  @Override
  public VehicleModel getVehicleModel(String name) {
    if (components.isEmpty()) {
      return super.getVehicleModel(name);
    }

    ModelComponent vehicle = components.get(name);
    if (vehicle instanceof VehicleModel) {
      return (VehicleModel) vehicle;
    }
    return null;
  }

}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralAdapterComponentsFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;

/**
 * A factory for various loopback specific instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LoopbackPeripheralAdapterComponentsFactory {

  /**
   * Creates a new loopback communication adapter for the given location.
   *
   * @param location The location.
   * @return A loopback communication adapter instance.
   */
  LoopbackPeripheralCommAdapter createLoopbackCommAdapter(TCSResourceReference<Location> location);
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayerGroupsTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import javax.swing.SwingUtilities;
import org.opentcs.guing.persistence.ModelManager;

/**
 * The table model for layer groups for the Model Editor application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class LayerGroupsTableModel
    extends AbstractLayerGroupsTableModel {

  /**
   * Creates a new instance.
   *
   * @param modelManager The model manager.
   * @param layerGroupEditor The layer group editor.
   */
  public LayerGroupsTableModel(ModelManager modelManager, LayerGroupEditor layerGroupEditor) {
    super(modelManager, layerGroupEditor);
  }

  @Override
  protected boolean isNameColumnEditable() {
    return true;
  }

  @Override
  protected boolean isVisibleColumnEditable() {
    return true;
  }

  @Override
  public void groupsInitialized() {
    // Once the layers are initialized we want to redraw the entire table to avoid any 
    // display errors.
    executeOnEventDispatcherThread(() -> fireTableDataChanged());
  }

  @Override
  public void groupsChanged() {
    // Update the entire table but don't use fireTableDataChanged() to preserve the current 
    // selection.
    executeOnEventDispatcherThread(() -> fireTableRowsUpdated(0, getRowCount() - 1));
  }

  @Override
  public void groupAdded() {
    // Groups are always added to the top (with regard to sorting).
    executeOnEventDispatcherThread(() -> fireTableRowsInserted(0, 0));
  }

  @Override
  public void groupRemoved() {
    // At this point, there's no way for us to determine the row the removed layer was in. The 
    // entry has already been remove from this table model's data source which is provided by
    // layersByOrdinal().
    // Workaround: Since the table now contains one entry less, pretend that the last entry was
    // deleted.
    executeOnEventDispatcherThread(() -> fireTableRowsDeleted(getRowCount(), getRowCount()));
  }

  /**
   * Ensures the given runnable is executed on the EDT.
   * If the runnable is already being called on the EDT, the runnable is executed immediately.
   * Otherwise it is scheduled for execution on the EDT.
   * <p>
   * Note: Deferring a runnable by scheduling it for execution on the EDT even though it would 
   * have already been executed on the EDT may lead to exceptions due to data inconsistency.
   * </p>
   *
   * @param runnable The runnable.
   */
  private void executeOnEventDispatcherThread(Runnable runnable) {
    if (SwingUtilities.isEventDispatchThread()) {
      runnable.run();
    }
    else {
      SwingUtilities.invokeLater(runnable);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/trigger/SingleOrderGenTrigger.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.trigger;

import java.util.Objects;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.guing.plugins.panels.loadgenerator.batchcreator.OrderBatchCreator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Triggers creation of transport orders only once.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SingleOrderGenTrigger
    implements OrderGenerationTrigger {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(SingleOrderGenTrigger.class);
  /**
   * The instance actually creating the new orders.
   */
  private final OrderBatchCreator orderBatchCreator;

  /**
   * Creates a new SingleOrderGenTrigger.
   *
   * @param orderBatchCreator The order batch creator
   */
  public SingleOrderGenTrigger(final OrderBatchCreator orderBatchCreator) {
    this.orderBatchCreator = Objects.requireNonNull(orderBatchCreator,
                                                    "orderBatchCreator is null");
  }

  @Override
  public void setTriggeringEnabled(boolean enabled) {
    if (enabled) {
      triggerOrderGeneration();
    }
  }

  @Override
  public void triggerOrderGeneration()
      throws KernelRuntimeException {
    try {
      if (orderBatchCreator != null) {
        orderBatchCreator.createOrderBatch();
      }
    }
    catch (KernelRuntimeException exc) {
      LOG.warn("Exception triggering order generation, terminating triggering", exc);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/LabeledFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.EventObject;
import java.util.LinkedList;
import org.jhotdraw.draw.AttributeKey;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.GraphicalCompositeFigure;
import org.jhotdraw.draw.handle.BoundsOutlineHandle;
import org.jhotdraw.draw.handle.DragHandle;
import org.jhotdraw.draw.handle.Handle;
import org.jhotdraw.draw.handle.MoveHandle;
import org.jhotdraw.draw.handle.ResizeHandleKit;
import org.opentcs.guing.components.drawing.course.OriginChangeListener;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;

/**
 * A figure that is labeled by another figure.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class LabeledFigure
    extends GraphicalCompositeFigure
    implements AttributesChangeListener, OriginChangeListener {

  /**
   * The figure of the label of this labeled figure.
   */
  private TCSLabelFigure fLabel;

  /**
   * Creates a new instance.
   */
  public LabeledFigure() {
  }

  public void setLabel(TCSLabelFigure label) {
    add(0, label);  // Allow only one label for each figure
    addFigureListener(label);
    label.setParent(this);
    fLabel = label;
  }

  public TCSLabelFigure getLabel() {
    return fLabel;
  }

  /**
   * Sets the visibility of the label.
   *
   * @param visible Indicates whether the label should be visible or not.
   */
  public void setLabelVisible(boolean visible) {
    fLabel.setLabelVisible(visible);
  }

  public abstract Shape getShape();

  @Override
  public TCSFigure getPresentationFigure() {
    return (TCSFigure) super.getPresentationFigure();
  }

  @Override
  public boolean handleMouseClick(Point2D.Double p, MouseEvent evt, DrawingView view) {
    boolean ret = getPresentationFigure().handleMouseClick(p, evt, view);

    return ret;
  }

  @Override
  public void changed() {
    super.changed();
    updateModel();
  }

  @Override
  public Collection<Handle> createHandles(int detailLevel) {
    LinkedList<Handle> handles = new LinkedList<>();

    switch (detailLevel) {
      case -1: // Mouse Moved
        handles.add(new BoundsOutlineHandle(getPresentationFigure(), false, true));
        break;

      case 0: // Mouse clicked
        MoveHandle.addMoveHandles(this, handles);
        for (Figure child : getChildren()) {
          MoveHandle.addMoveHandles(child, handles);
          handles.add(new DragHandle(child));
        }

        break;

      case 1: // Double-Click
        ResizeHandleKit.addResizeHandles(this, handles);
        break;

      default:
        break;
    }

    return handles;
  }

  @Override
  public <T> void set(AttributeKey<T> key, T newValue) {
    super.set(key, newValue);

    if (fLabel != null) {
      fLabel.set(key, newValue);
    }
  }

  @Override
  public void setBounds(Point2D.Double anchor, Point2D.Double lead) {
    basicSetPresentationFigureBounds(anchor, anchor);

    if (fLabel != null) {
      Point2D.Double p = getStartPoint();
      p.x += fLabel.getOffset().x;
      p.y += fLabel.getOffset().y;
      fLabel.setBounds(p, p);
    }
  }

  @Override
  public void originLocationChanged(EventObject event) {
    updateModel();
  }

  @Override
  public void originScaleChanged(EventObject event) {
    scaleModel(event);
  }

  public abstract void updateModel();
  /**
   * Scales the model coodinates accodring to changes to the layout scale.
   * 
   * @param event The event containing the layout scale change.
   */
  public abstract void scaleModel(EventObject event);

  @Override
  public LabeledFigure clone() {
    LabeledFigure clone = (LabeledFigure) super.clone();
    clone.fLabel = null;
    return clone;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/application/SplashFrame.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import java.lang.reflect.InvocationTargetException;
import static java.util.Objects.requireNonNull;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.opentcs.util.gui.Icons;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A frame for displaying the progress of longer-running processes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SplashFrame
    extends JFrame
    implements ProgressIndicator {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(SplashFrame.class);

  /**
   * Creates new form SplashFrame
   */
  public SplashFrame() {
    initComponents();
  }

  @Override
  public void initialize() {
    // Ensure this method is called on the event dispatcher thread.
    if (!SwingUtilities.isEventDispatchThread()) {
      try {
        SwingUtilities.invokeAndWait(new Runnable() {
          @Override
          public void run() {
            initialize();
          }
        });
      }
      catch (InterruptedException | InvocationTargetException exc) {
        LOG.warn("Unexpected exception", exc);
      }
      return;
    }
    setVisible(true);
    setProgress(0, "");
  }

  @Override
  public void setProgress(ProgressStatus progressStatus) {
    requireNonNull(progressStatus, "progressStatus");

    setProgress(progressStatus.getPercentage(), progressStatus.getStatusDescription());
  }

  @Override
  public void terminate() {
    // Ensure this method is called on the event dispatcher thread.
    if (!SwingUtilities.isEventDispatchThread()) {
      try {
        SwingUtilities.invokeAndWait(new Runnable() {
          @Override
          public void run() {
            terminate();
          }
        });
      }
      catch (InterruptedException | InvocationTargetException exc) {
        LOG.warn("Unexpected exception", exc);
      }
      return;
    }
    dispose();
  }

  private void setProgress(final int percent, final String message) {
    // Ensure this method is called on the event dispatcher thread.
    if (!SwingUtilities.isEventDispatchThread()) {
      try {
        SwingUtilities.invokeAndWait(new Runnable() {
          @Override
          public void run() {
            setProgress(percent, message);
          }
        });
      }
      catch (InterruptedException | InvocationTargetException exc) {
        LOG.warn("Unexpected exception", exc);
      }
      return;
    }
    labelMessage.setText(message);
    progressBar.setValue(percent);
    update(getGraphics());
    toFront();
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        panel = new javax.swing.JPanel();
        labelImage = new javax.swing.JLabel();
        labelMessage = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/system"); // NOI18N
        setTitle(bundle.getString("splashFrame.title.text")); // NOI18N
        setBackground(new java.awt.Color(255, 255, 255));
        setIconImages(Icons.getOpenTCSIcons());
        setUndecorated(true);
        getContentPane().setLayout(new java.awt.GridBagLayout());

        panel.setBackground(new java.awt.Color(255, 255, 255));
        panel.setLayout(new java.awt.GridBagLayout());

        labelImage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/opentcs/guing/res/symbols/openTCS/splash.320x152.gif"))); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
        panel.add(labelImage, gridBagConstraints);

        labelMessage.setBackground(new java.awt.Color(255, 255, 255));
        labelMessage.setFont(new java.awt.Font("Arial", 1, 12)); // NOI18N
        labelMessage.setText(bundle.getString("splashFrame.label_message.text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.5;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 4);
        panel.add(labelMessage, gridBagConstraints);

        progressBar.setBackground(new java.awt.Color(255, 255, 255));
        progressBar.setForeground(new java.awt.Color(153, 153, 255));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
        gridBagConstraints.weighty = 0.5;
        panel.add(progressBar, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(panel, gridBagConstraints);

        setSize(new java.awt.Dimension(316, 186));
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel labelImage;
    private javax.swing.JLabel labelMessage;
    private javax.swing.JPanel panel;
    private javax.swing.JProgressBar progressBar;
    // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/KernelExtension.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

import org.opentcs.components.Lifecycle;

/**
 * Declares the methods that a generic kernel extension must implement.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface KernelExtension
    extends Lifecycle {
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/PluggablePanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import javax.swing.JPanel;
import org.opentcs.components.Lifecycle;

/**
 * Declares methods that a pluggable panel should provide for the enclosing
 * application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class PluggablePanel
    extends JPanel
    implements Lifecycle {

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerGroupChangeListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

/**
 * Listens for changes to/updates on layer group data.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerGroupChangeListener {

  /**
   * Notifies the listener that the layer group data has been initialized.
   */
  void groupsInitialized();

  /**
   * Notifies the listener that some layer group data has changed.
   */
  void groupsChanged();

  /**
   * Notifies the listener that a layer group has been added.
   */
  void groupAdded();

  /**
   * Notifies the listener that a layer group has been removed.
   */
  void groupRemoved();
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/common/LoggingScheduledThreadPoolExecutor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.common;

import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Extends the {@link ScheduledThreadPoolExecutor} by logging exceptions thrown by scheduled tasks.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoggingScheduledThreadPoolExecutor
    extends ScheduledThreadPoolExecutor {

  /**
   * This class's logger.
   */
  private static final Logger LOG
      = LoggerFactory.getLogger(LoggingScheduledThreadPoolExecutor.class);

  /**
   * Creates a new instance.
   *
   * @param corePoolSize The number of threads to keep in the pool.
   * @param threadFactory The factory to use when the executor creates a new thread.
   * @throws IllegalArgumentException If {@code corePoolSize < 0}
   * @throws NullPointerException If {@code threadFactory} is null
   */
  public LoggingScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {
    super(corePoolSize, threadFactory);
  }

  @Override
  protected void afterExecute(Runnable r, Throwable t) {
    super.afterExecute(r, t);
    if (t == null && r instanceof Future<?>) {
      try {
        Future<?> future = (Future<?>) r;
        if (future.isDone()) {
          future.get();
        }
        else if (isPeriodic(future)) {
          // Periodic futures will never be done
          return;
        }
        else {
          LOG.debug("Future was not done: {}", future);
        }
      }
      catch (ExecutionException ee) {
        LOG.warn("Unhandled exception in executed task", ee.getCause());
      }
      catch (CancellationException ce) {
        LOG.debug("Task was cancelled", ce);
      }
      catch (InterruptedException ie) {
        LOG.debug("Interrupted during Future.get()", ie);
        // Ignore/Reset
        Thread.currentThread().interrupt();
      }
    }
    if (t != null) {
      LOG.error("Abrupt termination", t);
    }
  }

  private boolean isPeriodic(Future<?> future) {
    if (future instanceof RunnableScheduledFuture<?>) {
      RunnableScheduledFuture<?> runnableFuture = (RunnableScheduledFuture<?>) future;
      if (runnableFuture.isPeriodic()) {
        return true;
      }
    }
    return false;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/layer/LayerManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import org.opentcs.components.Lifecycle;
import org.opentcs.util.event.EventHandler;

/**
 * Organizes the layers in a plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerManager
    extends Lifecycle,
            LayerEditor,
            EventHandler {

  /**
   * Sets the listener for layer data changes.
   *
   * @param listener The listener for layer data changes.
   */
  void setLayerChangeListener(LayerChangeListener listener);

  /**
   * Returns whether the layer with the given layer ID contains any components.
   *
   * @param layerId The ID of the layer.
   * @return Whether the layer contains any components.
   */
  boolean containsComponents(int layerId);
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/SetVehiclePropertyCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;

/**
 * A command to set a vehicle's property.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetVehiclePropertyCommand
    implements AdapterCommand {

  /**
   * The property key to set.
   */
  private final String key;
  /**
   * The property value to set.
   */
  private final String value;

  /**
   * Creates a new instance.
   *
   * @param key The property key to set.
   * @param value The property value to set.
   */
  public SetVehiclePropertyCommand(@Nonnull String key, @Nullable String value) {
    this.key = requireNonNull(key, "key");
    this.value = value;
  }

  @Override
  public void execute(VehicleCommAdapter adapter) {
    adapter.getProcessModel().setVehicleProperty(key, value);
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/model/elements/LinkModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.model.elements;

import java.util.ResourceBundle;
import static org.opentcs.guing.I18nPlantOverviewBase.BUNDLE_PATH;
import org.opentcs.guing.components.layer.NullLayerWrapper;
import org.opentcs.guing.components.properties.type.LayerWrapperProperty;
import org.opentcs.guing.components.properties.type.LinkActionsProperty;
import org.opentcs.guing.components.properties.type.StringProperty;
import org.opentcs.guing.components.properties.type.StringSetProperty;

/**
 * Basic implementation of link between a point and a location.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class LinkModel
    extends AbstractConnection {

  /**
   * The key for the possible actions on the location.
   */
  public static final String ALLOWED_OPERATIONS = "AllowedOperations";
  /**
   * This class's resource bundle.
   */
  private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_PATH);

  /**
   * Creates a new instance.
   */
  public LinkModel() {
    createProperties();
  }

  /**
   * Returns the connected point.
   *
   * @return The model of the connected Point.
   */
  public PointModel getPoint() {
    if (getStartComponent() instanceof PointModel) {
      return (PointModel) getStartComponent();
    }

    if (getEndComponent() instanceof PointModel) {
      return (PointModel) getEndComponent();
    }

    return null;
  }

  /**
   * Returns the connected location.
   *
   * @return The model of the connected Location.
   */
  public LocationModel getLocation() {
    if (getStartComponent() instanceof LocationModel) {
      return (LocationModel) getStartComponent();
    }

    if (getEndComponent() instanceof LocationModel) {
      return (LocationModel) getEndComponent();
    }

    return null;
  }

  @Override // AbstractModelComponent
  public String getDescription() {
    return bundle.getString("linkModel.description");
  }

  public StringSetProperty getPropertyAllowedOperations() {
    return (StringSetProperty) getProperty(ALLOWED_OPERATIONS);
  }

  private void createProperties() {
    StringProperty pName = new StringProperty(this);
    pName.setDescription(bundle.getString("linkModel.property_name.description"));
    pName.setHelptext(bundle.getString("linkModel.property_name.helptext"));
    // The name of a link cannot be changed because it is not stored in the kernel model
    pName.setModellingEditable(false);
    setProperty(NAME, pName);

    StringSetProperty pOperations = new LinkActionsProperty(this);
    pOperations.setDescription(bundle.getString("linkModel.property_operations.description"));
    pOperations.setHelptext(bundle.getString("linkModel.property_operations.helptext"));
    setProperty(ALLOWED_OPERATIONS, pOperations);

    StringProperty startComponent = new StringProperty(this);
    startComponent.setDescription(bundle.getString("linkModel.property_startComponent.description"));
    startComponent.setModellingEditable(false);
    startComponent.setOperatingEditable(false);
    setProperty(START_COMPONENT, startComponent);

    StringProperty endComponent = new StringProperty(this);
    endComponent.setDescription(bundle.getString("linkModel.property_endComponent.description"));
    endComponent.setModellingEditable(false);
    endComponent.setOperatingEditable(false);
    setProperty(END_COMPONENT, endComponent);
    
    LayerWrapperProperty pLayerWrapper = new LayerWrapperProperty(this, new NullLayerWrapper());
    pLayerWrapper.setDescription(bundle.getString("linkModel.property_layerWrapper.description"));
    pLayerWrapper.setHelptext(bundle.getString("linkModel.property_layerWrapper.helptext"));
    pLayerWrapper.setModellingEditable(false);
    setProperty(LAYER_WRAPPER, pLayerWrapper);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/management/PeripheralCommAdapterPanelFactory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals.management;

import java.util.List;
import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;

/**
 * Provides peripheral comm adapter specific panels used for interaction and displaying information.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface PeripheralCommAdapterPanelFactory
    extends Lifecycle {

  /**
   * Returns a list of {@link PeripheralCommAdapterPanel}s.
   *
   * @param description The description to create panels for.
   * @param location The location to create panels for.
   * @param processModel The current state of the process model a panel may want to initialize its
   * components with.
   * @return A list of comm adapter panels, or an empty list, if this factory cannot provide panels
   * for the given description.
   */
  List<PeripheralCommAdapterPanel> getPanelsFor(
      @Nonnull PeripheralCommAdapterDescription description,
      @Nonnull TCSResourceReference<Location> location,
      @Nonnull PeripheralProcessModel processModel);
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/recharging/RechargeIdleVehiclesPhase.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.recharging;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import javax.inject.Inject;
import org.opentcs.access.to.order.DestinationCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalTransportOrderService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.Phase;
import org.opentcs.strategies.basic.dispatching.TransportOrderUtil;
import org.opentcs.strategies.basic.dispatching.selection.candidates.CompositeAssignmentCandidateSelectionFilter;
import org.opentcs.strategies.basic.dispatching.selection.vehicles.CompositeRechargeVehicleSelectionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Creates recharging orders for any vehicles with a degraded energy level.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RechargeIdleVehiclesPhase
    implements Phase {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(RechargeIdleVehiclesPhase.class);
  /**
   * The transport order service.
   */
  private final InternalTransportOrderService orderService;
  /**
   * The strategy used for finding suitable recharge locations.
   */
  private final RechargePositionSupplier rechargePosSupplier;
  /**
   * The Router instance calculating route costs.
   */
  private final Router router;
  /**
   * A collection of predicates for filtering assignment candidates.
   */
  private final CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter;

  private final CompositeRechargeVehicleSelectionFilter vehicleSelectionFilter;

  private final TransportOrderUtil transportOrderUtil;
  /**
   * The dispatcher configuration.
   */
  private final DefaultDispatcherConfiguration configuration;
  /**
   * Indicates whether this component is initialized.
   */
  private boolean initialized;

  @Inject
  public RechargeIdleVehiclesPhase(
      InternalTransportOrderService orderService,
      RechargePositionSupplier rechargePosSupplier,
      Router router,
      CompositeAssignmentCandidateSelectionFilter assignmentCandidateSelectionFilter,
      CompositeRechargeVehicleSelectionFilter vehicleSelectionFilter,
      TransportOrderUtil transportOrderUtil,
      DefaultDispatcherConfiguration configuration) {
    this.router = requireNonNull(router, "router");
    this.orderService = requireNonNull(orderService, "orderService");
    this.rechargePosSupplier = requireNonNull(rechargePosSupplier, "rechargePosSupplier");
    this.assignmentCandidateSelectionFilter = requireNonNull(assignmentCandidateSelectionFilter,
                                                             "assignmentCandidateSelectionFilter");
    this.vehicleSelectionFilter = requireNonNull(vehicleSelectionFilter, "vehicleSelectionFilter");
    this.transportOrderUtil = requireNonNull(transportOrderUtil, "transportOrderUtil");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    rechargePosSupplier.initialize();

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    rechargePosSupplier.terminate();

    initialized = false;
  }

  @Override
  public void run() {
    if (!configuration.rechargeIdleVehicles()) {
      return;
    }

    orderService.fetchObjects(Vehicle.class).stream()
        .filter(vehicle -> vehicleSelectionFilter.apply(vehicle).isEmpty())
        .forEach(vehicle -> createRechargeOrder(vehicle));
  }

  private void createRechargeOrder(Vehicle vehicle) {
    List<DriveOrder.Destination> rechargeDests = rechargePosSupplier.findRechargeSequence(vehicle);
    LOG.debug("Recharge sequence for {}: {}", vehicle, rechargeDests);

    if (rechargeDests.isEmpty()) {
      LOG.info("{}: Did not find a suitable recharge sequence.", vehicle.getName());
      return;
    }

    List<DestinationCreationTO> chargeDests = new ArrayList<>(rechargeDests.size());
    for (DriveOrder.Destination dest : rechargeDests) {
      chargeDests.add(
          new DestinationCreationTO(dest.getDestination().getName(), dest.getOperation())
              .withProperties(dest.getProperties())
      );
    }
    // Create a transport order for recharging and verify its processability.
    // The recharge order may be withdrawn unless its energy level is critical.
    TransportOrder rechargeOrder = orderService.createTransportOrder(
        new TransportOrderCreationTO("Recharge-", chargeDests)
            .withIncompleteName(true)
            .withIntendedVehicleName(vehicle.getName())
            .withDispensable(!vehicle.isEnergyLevelCritical())
    );

    Point vehiclePosition = orderService.fetchObject(Point.class, vehicle.getCurrentPosition());
    Optional<AssignmentCandidate> candidate = computeCandidate(vehicle,
                                                               vehiclePosition,
                                                               rechargeOrder)
        .filter(c -> assignmentCandidateSelectionFilter.apply(c).isEmpty());
    // XXX Change this to Optional.ifPresentOrElse() once we're at Java 9+.
    if (candidate.isPresent()) {
      transportOrderUtil.assignTransportOrder(candidate.get().getVehicle(),
                                              candidate.get().getTransportOrder(),
                                              candidate.get().getDriveOrders());
    }
    else {
      // Mark the order as failed, since the vehicle cannot execute it.
      orderService.updateTransportOrderState(rechargeOrder.getReference(),
                                             TransportOrder.State.FAILED);
    }
  }

  private Optional<AssignmentCandidate> computeCandidate(Vehicle vehicle,
                                                         Point vehiclePosition,
                                                         TransportOrder order) {
    return router.getRoute(vehicle, vehiclePosition, order)
        .map(driveOrders -> new AssignmentCandidate(vehicle, order, driveOrders));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/LocationCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.visualization.LocationRepresentation;

/**
 * A transfer object describing a location in a plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LocationCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The name of this location's type.
   */
  @Nonnull
  private String typeName;
  /**
   * This location's position (in mm).
   */
  @Nonnull
  private Triple position;
  /**
   * The links attaching points to this location.
   * This is a map of point names to allowed operations.
   */
  @Nonnull
  private Map<String, Set<String>> links = new HashMap<>();
  /**
   * A flag for marking this location as locked (i.e. to prevent vehicles from using it).
   */
  private boolean locked;
  /**
   * The information regarding the grahical representation of this location.
   */
  private Layout layout = new Layout();

  /**
   * Creates a new instance
   *
   * @param name The name of this location.
   * @param typeName The name of this location's type.
   * @param position The position of this location.
   */
  public LocationCreationTO(@Nonnull String name,
                            @Nonnull String typeName,
                            @Nonnull Triple position) {
    super(name);
    this.typeName = requireNonNull(typeName, "typeName");
    this.position = position;
  }

  private LocationCreationTO(@Nonnull String name,
                             @Nonnull Map<String, String> properties,
                             @Nonnull String typeName,
                             @Nonnull Triple position,
                             @Nonnull Map<String, Set<String>> links,
                             boolean locked,
                             @Nonnull Layout layout) {
    super(name, properties);
    this.typeName = requireNonNull(typeName, "typeName");
    this.position = requireNonNull(position, "position");
    this.links = requireNonNull(links, "links");
    this.locked = locked;
    this.layout = requireNonNull(layout, "layout");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new name.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public LocationCreationTO withName(@Nonnull String name) {
    return new LocationCreationTO(name,
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Returns the name of this location's type.
   *
   * @return The name of this location's type.
   */
  @Nonnull
  public String getTypeName() {
    return typeName;
  }

  /**
   * Creates a copy of this object with the location's type.
   *
   * @param typeName The location type.
   * @return A copy of this object, differing in the given type.
   */
  public LocationCreationTO withTypeName(@Nonnull String typeName) {
    return new LocationCreationTO(getName(),
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Returns the position of this location (in mm).
   *
   * @return The position of this location (in mm).
   */
  @Nonnull
  public Triple getPosition() {
    return position;
  }

  /**
   * Creates a copy of this object with the given position (in mm).
   *
   * @param position the new position of this location (in mm).
   * @return A copy of this object, differing in the given position.
   */
  public LocationCreationTO withPosition(@Nonnull Triple position) {
    return new LocationCreationTO(getName(),
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Returns the links attaching points to this location.
   * This is a map of point names to allowed operations.
   *
   * @return The links attaching points to this location.
   */
  @Nonnull
  public Map<String, Set<String>> getLinks() {
    return Collections.unmodifiableMap(links);
  }

  /**
   * Creates a copy of this object with the given links that attach points to this location.
   *
   * @param links the new links. This is supposed to be a map of point names to allowed operations.
   * @return A copy of this object, differing in the given links.
   */
  public LocationCreationTO withLinks(@Nonnull Map<String, Set<String>> links) {
    return new LocationCreationTO(getName(),
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Creates a copy of this object with the given links that attach points to this location.
   *
   * @param pointName The name of the point linked to.
   * @param allowedOperations The operations allowed at the point.
   * @return A copy of this object, differing in the given link.
   */
  public LocationCreationTO withLink(@Nonnull String pointName,
                                     @Nonnull Set<String> allowedOperations) {
    return new LocationCreationTO(getName(),
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  mapWithMapping(links, pointName, allowedOperations),
                                  locked,
                                  layout);
  }

  /**
   * Returns the lock status of this location (i.e. whether it my be used by vehicles or not).
   *
   * @return {@code true} if this location is currently locked (i.e. it may not be used
   * by vehicles), else {@code false}.
   */
  public boolean isLocked() {
    return locked;
  }

  /**
   * Creates a copy of this object with the given locked flag.
   *
   * @param locked The new locked attribute.
   * @return A copy of this object, differing in the locked attribute.
   */
  public LocationCreationTO withLocked(boolean locked) {
    return new LocationCreationTO(getName(),
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public LocationCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new LocationCreationTO(getName(),
                                  properties,
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public LocationCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new LocationCreationTO(getName(),
                                  propertiesWith(key, value),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  /**
   * Returns the information regarding the grahical representation of this location.
   *
   * @return The information regarding the grahical representation of this location.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LocationCreationTO withLayout(Layout layout) {
    return new LocationCreationTO(getName(),
                                  getModifiableProperties(),
                                  typeName,
                                  position,
                                  links,
                                  locked,
                                  layout);
  }

  @Override
  public String toString() {
    return "LocationCreationTO{"
        + "name=" + getName()
        + ", typeName=" + typeName
        + ", position=" + position
        + ", links=" + links
        + ", locked=" + locked
        + ", layout=" + layout
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Contains information regarding the grahical representation of a location.
   */
  public static class Layout
      implements Serializable {

    /**
     * The coordinates at which the location is to be drawn (in mm).
     */
    private final Couple position;
    /**
     * The offset of the label's position to the location's position (in lu).
     */
    private final Couple labelOffset;
    /**
     * The location representation to use.
     */
    private final LocationRepresentation locationRepresentation;
    /**
     * The ID of the layer on which the location is to be drawn.
     */
    private final int layerId;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(new Couple(0, 0), new Couple(0, 0), LocationRepresentation.DEFAULT, 0);
    }

    /**
     * Creates a new instance.
     *
     * @param position The coordinates at which the location is to be drawn (in mm).
     * @param labelOffset The offset of the label's location to the point's position (in lu).
     * @param locationRepresentation The location representation to use.
     * @param layerId The ID of the layer on which the location is to be drawn.
     */
    public Layout(Couple position,
                  Couple labelOffset,
                  LocationRepresentation locationRepresentation,
                  int layerId) {
      this.position = requireNonNull(position, "position");
      this.labelOffset = requireNonNull(labelOffset, "labelOffset");
      this.locationRepresentation = requireNonNull(locationRepresentation,
                                                   "locationRepresentation");
      this.layerId = layerId;
    }

    /**
     * Returns the coordinates at which the location is to be drawn (in mm).
     *
     * @return The coordinates at which the location is to be drawn (in mm).
     */
    public Couple getPosition() {
      return position;
    }

    /**
     * Creates a copy of this object, with the given position.
     *
     * @param position The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withPosition(Couple position) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    /**
     * Returns the offset of the label's position to the location's position (in lu).
     *
     * @return The offset of the label's position to the location's position (in lu).
     */
    public Couple getLabelOffset() {
      return labelOffset;
    }

    /**
     * Creates a copy of this object, with the given X label offset.
     *
     * @param labelOffset The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLabelOffset(Couple labelOffset) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    /**
     * Returns the location representation to use.
     *
     * @return The location representation to use.
     */
    public LocationRepresentation getLocationRepresentation() {
      return locationRepresentation;
    }

    /**
     * Creates a copy of this object, with the given location representation.
     *
     * @param locationRepresentation The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLocationRepresentation(LocationRepresentation locationRepresentation) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    /**
     * Returns the ID of the layer on which the location is to be drawn.
     *
     * @return The layer ID.
     */
    public int getLayerId() {
      return layerId;
    }

    /**
     * Creates a copy of this object, with the given layer ID.
     *
     * @param layerId The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLayerId(int layerId) {
      return new Layout(position,
                        labelOffset,
                        locationRepresentation,
                        layerId);
    }

    @Override
    public String toString() {
      return "Layout{"
          + "position=" + position
          + ", labelOffset=" + labelOffset
          + ", locationRepresentation=" + locationRepresentation
          + ", layerId=" + layerId
          + '}';
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/dialogs/EditDriveOrderPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dialogs;

import static com.google.common.base.Preconditions.checkArgument;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import javax.swing.DefaultComboBoxModel;
import org.opentcs.guing.components.properties.type.StringSetProperty;
import org.opentcs.guing.model.AbstractConnectableModelComponent;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Panel to edit a drive order.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class EditDriveOrderPanel
    extends DialogContent {

  /**
   * Available locations.
   */
  private final List<LocationModel> fLocations;
  /**
   * The selected location.
   */
  private AbstractConnectableModelComponent fSelectedLocation;
  /**
   * Selected action.
   */
  private String fSelectedAction;

  /**
   * Creates new form EditDriveOrderPanel
   *
   * @param locations available locations.
   */
  public EditDriveOrderPanel(List<LocationModel> locations) {
    initComponents();
    fLocations = sortLocations(locations);
    setDialogTitle(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.CREATETO_PATH)
        .getString("editDriverOrderPanel.create.title"));
  }

  /**
   * Creates new form EditDriveOrderPanel
   *
   * @param locations available locations.
   * @param location selected location
   * @param action selected action.
   */
  public EditDriveOrderPanel(List<LocationModel> locations,
                             AbstractConnectableModelComponent location, String action) {
    checkArgument(location instanceof PointModel || location instanceof LocationModel,
                  String.format("Selected location has to be of type PointModel or LocationModel "
                      + "and not \"%s\".", location.getClass().getName()));
    initComponents();
    fLocations = sortLocations(locations);
    fSelectedLocation = location;
    fSelectedAction = action;
    setDialogTitle(ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.CREATETO_PATH)
        .getString("editDriverOrderPanel.edit.title"));
  }

  /**
   * Sorts a list of locations based on their name.
   *
   * @param locations list of locations to sort.
   * @return The list of sorted locations.
   */
  private List<LocationModel> sortLocations(List<LocationModel> locations) {
    Comparator<LocationModel> c = new Comparator<LocationModel>() {

      @Override
      public int compare(LocationModel o1, LocationModel o2) {
        String s1 = o1.getName().toLowerCase();
        String s2 = o2.getName().toLowerCase();
        return s1.compareTo(s2);
      }
    };

    List<LocationModel> result = new ArrayList<>(locations);
    Collections.sort(result, c);

    return result;
  }

  @Override
  public void update() {
  }

  @Override
  public void initFields() {
    for (LocationModel s : fLocations) {
      locationComboBox.addItem(s.getName());
    }

    if (fSelectedLocation != null) {
      locationComboBox.setSelectedItem(fSelectedLocation.getName());
    }
    else if (locationComboBox.getItemCount() > 0) {
      locationComboBox.setSelectedIndex(0);
    }

    if (fSelectedAction != null) {
      actionComboBox.setSelectedItem(fSelectedAction);
    }
  }

  /**
   * Returns the selected location.
   *
   * @return The selected location
   */
  public Optional<LocationModel> getSelectedLocation() {
    int index = locationComboBox.getSelectedIndex();
    return index == -1 ? Optional.empty() : Optional.ofNullable(fLocations.get(index));
  }

  /**
   * Returns the selected action.
   *
   * @return The selected action.
   */
  public Optional<String> getSelectedAction() {
    return Optional.ofNullable((String) actionComboBox.getSelectedItem());
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    stationLabel = new javax.swing.JLabel();
    locationComboBox = new javax.swing.JComboBox<>();
    actionLabel = new javax.swing.JLabel();
    actionComboBox = new javax.swing.JComboBox<>();

    java.awt.GridBagLayout layout = new java.awt.GridBagLayout();
    layout.columnWidths = new int[] {0, 5, 0};
    layout.rowHeights = new int[] {0, 5, 0};
    setLayout(layout);

    stationLabel.setFont(stationLabel.getFont());
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/plantoverview/operating/dialogs/createTransportOrder"); // NOI18N
    stationLabel.setText(bundle.getString("editDriverOrderPanel.label_location.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
    add(stationLabel, gridBagConstraints);

    locationComboBox.setFont(locationComboBox.getFont());
    locationComboBox.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        locationComboBoxActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 0.5;
    add(locationComboBox, gridBagConstraints);

    actionLabel.setFont(actionLabel.getFont());
    actionLabel.setText(bundle.getString("editDriverOrderPanel.label_action.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
    add(actionLabel, gridBagConstraints);

    actionComboBox.setFont(actionComboBox.getFont());
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 0.5;
    add(actionComboBox, gridBagConstraints);
  }// </editor-fold>//GEN-END:initComponents
  // CHECKSTYLE:ON

  /**
   * Updates the contents of the ComboBox with the allowed operations.
   *
   * @param evt the event.
   */
  private void locationComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_locationComboBoxActionPerformed
    DefaultComboBoxModel<String> model
        = (DefaultComboBoxModel<String>) actionComboBox.getModel();
    model.removeAllElements();

    getSelectedLocation().ifPresent(location -> {
      LocationTypeModel type = location.getLocationType();
      StringSetProperty p = type.getPropertyAllowedOperations();
      for (String item : new ArrayList<>(type.getPropertyAllowedOperations().getItems())) {
        model.addElement(item);
      }

      if (model.getSize() > 0) {
        actionComboBox.setSelectedIndex(0);
      }
    });
  }//GEN-LAST:event_locationComboBoxActionPerformed

  // CHECKSTYLE:OFF
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JComboBox<String> actionComboBox;
  private javax.swing.JLabel actionLabel;
  private javax.swing.JComboBox<String> locationComboBox;
  private javax.swing.JLabel stationLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-Common/src/test/java/org/opentcs/util/UniqueStringGeneratorTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 * A test case for class UniqueStringGenerator.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class UniqueStringGeneratorTest {

  private static final String PREFIX = "TestPrefix";

  private static final String PATTERN_ONE_DIGIT = "0";

  private static final String PATTERN_TWO_DIGITS = "00";

  private UniqueStringGenerator<Object> generator;

  @Before
  public void setUp() {
    generator = new UniqueStringGenerator<>();
  }

  @Test
  public void testRepeatedGenerationWithoutModification() {
    String generatedString = generator.getUniqueString(PREFIX,
                                                       PATTERN_TWO_DIGITS);
    assertEquals(PREFIX + "01", generatedString);
    generatedString = generator.getUniqueString(PREFIX, PATTERN_TWO_DIGITS);
    assertEquals(PREFIX + "01", generatedString);
  }

  @Test
  public void shouldProvideConfiguredPatterns() {
    final String namePatternPrefix = "SomePrefix";
    final String namePatterPrefix2 = "AnotherPrefix";
    final Object selector = new Object();
    final Object selector2 = new Object();

    generator.registerNamePattern(selector, namePatternPrefix, "0000");
    generator.registerNamePattern(selector2, namePatterPrefix2, "0000");

    assertEquals(namePatternPrefix + "0001",
                 generator.getUniqueString(selector));
    assertEquals(namePatterPrefix2 + "0001",
                 generator.getUniqueString(selector2));
  }

  @Test
  public void testRepeatedGenerationWithAddition() {
    String generatedString = generator.getUniqueString(PREFIX,
                                                       PATTERN_TWO_DIGITS);
    assertEquals(PREFIX + "01", generatedString);
    generator.addString(generatedString);
    generatedString = generator.getUniqueString(PREFIX, PATTERN_TWO_DIGITS);
    assertEquals(PREFIX + "02", generatedString);
  }

  @Test
  public void testNullPrefix() {
    String generatedString = generator.getUniqueString(null,
                                                       PATTERN_ONE_DIGIT);
    assertEquals("1", generatedString);
  }

  @Test
  public void shouldHaveString() {
    generator.addString("some string");
    assertTrue(generator.hasString("some string"));
  }
  
  @Test
  public void shouldNotHaveString() {
    generator.addString("some string");
    assertFalse(generator.hasString("some other string"));
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/AbstractTableContent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.inject.Provider;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import org.opentcs.guing.components.properties.event.TableChangeListener;
import org.opentcs.guing.components.properties.event.TableSelectionChangeEvent;
import org.opentcs.guing.components.properties.table.AttributesTable;
import org.opentcs.guing.components.properties.type.Property;

/**
 * Base implementation for content that displays model properties in a table.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class AbstractTableContent
    extends AbstractAttributesContent
    implements TableChangeListener {

  /**
   * The table that shows the properties.
   */
  protected AttributesTable fTable;
  /**
   * The cell editors.
   */
  protected List<TableCellEditor> fCellEditors = new ArrayList<>();
  /**
   * Indicates that changes to the tabel model should also update the model component.
   */
  protected boolean fEvaluateTableChanges = true;
  /**
   * Provides attribute tables.
   */
  private final Provider<AttributesTable> tableProvider;

  /**
   * Creates a new instance.
   *
   * @param tableProvider Provides attribute tables.
   */
  public AbstractTableContent(Provider<AttributesTable> tableProvider) {
    this.tableProvider = requireNonNull(tableProvider, "tableProvider");
  }

  @Override // AbstractAttributesContent
  protected JComponent createComponent() {
    JPanel component = new JPanel();

    initTable();
    JScrollPane scrollPane = new JScrollPane(fTable);

    component.setLayout(new BorderLayout());
    component.add(scrollPane, BorderLayout.CENTER);

    return component;
  }

  @Override // TableChangeListener
  public void tableSelectionChanged(TableSelectionChangeEvent e) {
  }

  @Override // TableChangeListener
  public void tableModelChanged() {
  }

  /**
   * Initialises the table.
   */
  protected void initTable() {
    fTable = tableProvider.get();
    setTableCellRenderers();
    setTableCellEditors();
    fTable.addTableChangeListener(this);
  }

  /**
   * Set the table cell renderers.
   */
  protected void setTableCellRenderers() {
  }

  /**
   * Set the table cell editors.
   */
  protected void setTableCellEditors() {
  }

  /**
   * Set new table content.
   *
   * @param content A map from property name to property.
   */
  protected void setTableContent(Map<String, Property> content) {
    fEvaluateTableChanges = false;

    TableColumnModel columnModel = fTable.getColumnModel();
    int[] widths = new int[columnModel.getColumnCount()];

    for (int i = 0; i < widths.length; i++) {
      widths[i] = columnModel.getColumn(i).getWidth();
    }

    fTable.setModel(createTableModel(content));

    for (int i = 0; i < widths.length; i++) {
      columnModel.getColumn(i).setPreferredWidth(widths[i]);
    }

    fEvaluateTableChanges = true;
  }

  /**
   * Creates a new table model from the content.
   *
   * @param content Map from property name to property.
   * @return A table model that represents the content.
   */
  protected abstract TableModel createTableModel(Map<String, Property> content);

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemotePeripheralDispatcherServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.PeripheralDispatcherService;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;

/**
 * The default implementation of the peripheral dispatcher service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class RemotePeripheralDispatcherServiceProxy
    extends AbstractRemoteServiceProxy<RemotePeripheralDispatcherService>
    implements PeripheralDispatcherService {

  @Override
  public void dispatch()
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().dispatch(getClientId());
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void withdrawByLocation(TCSResourceReference<Location> locationRef)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().withdrawByLocation(getClientId(), locationRef);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/course/OriginChangeListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.course;

import java.util.EventObject;

/**
 * Interface for classes that want to be notified about origin position changes
 * and origin scale changes.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public interface OriginChangeListener {

  /**
   * Event that the position of the origin has changed.
   *
   * @param evt event that the position has changed.
   */
  void originLocationChanged(EventObject evt);

  /**
   * Event that the scale of the origin has changed.
   *
   * @param evt event that the scale of the origin has changed.
   */
  void originScaleChanged(EventObject evt);
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/persistence/package-info.java<|end_filename|>
/**
 * Classes for persisting and materializing openTCS data.
 */
package org.opentcs.kernel.persistence;


<|start_filename|>openTCS-Kernel-Extension-HTTP-Services/src/main/java/org/opentcs/kernel/extensions/servicewebapi/v1/status/StatusEventDispatcher.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.servicewebapi.v1.status;

import java.util.Collection;
import static java.util.Objects.requireNonNull;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectEvent;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.kernel.extensions.servicewebapi.ServiceWebApiConfiguration;
import org.opentcs.kernel.extensions.servicewebapi.v1.status.binding.OrderStatusMessage;
import org.opentcs.kernel.extensions.servicewebapi.v1.status.binding.StatusMessage;
import org.opentcs.kernel.extensions.servicewebapi.v1.status.binding.StatusMessageList;
import org.opentcs.kernel.extensions.servicewebapi.v1.status.binding.VehicleStatusMessage;
import static org.opentcs.util.Assertions.checkInRange;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides descriptions of recent events.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StatusEventDispatcher
    implements Lifecycle,
               EventHandler {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(StatusEventDispatcher.class);
  /**
   * The interface configuration.
   */
  private final ServiceWebApiConfiguration configuration;
  /**
   * Where we register for application events.
   */
  private final EventSource eventSource;
  /**
   * The events collected.
   */
  private final SortedMap<Long, StatusMessage> events = new TreeMap<>();
  /**
   * The number of events collected so far.
   */
  private long eventCount;
  /**
   * Whether this instance is initialized.
   */
  private boolean initialized;

  @Inject
  public StatusEventDispatcher(ServiceWebApiConfiguration configuration,
                               @ApplicationEventBus EventSource eventSource) {
    this.configuration = requireNonNull(configuration, "configuration");
    this.eventSource = requireNonNull(eventSource, "eventSource");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    synchronized (events) {
      eventCount = 0;
      events.clear();
    }

    eventSource.subscribe(this);

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    eventSource.unsubscribe(this);

    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (!(event instanceof TCSObjectEvent)) {
      return;
    }
    TCSObject<?> object = ((TCSObjectEvent) event).getCurrentOrPreviousObjectState();
    if (object instanceof TransportOrder) {
      synchronized (events) {
        addOrderStatusMessage((TransportOrder) object, eventCount);
        eventCount++;
        cleanUpEvents();
        events.notifyAll();
      }
    }
    else if (object instanceof Vehicle) {
      synchronized (events) {
        addVehicleStatusMessage((Vehicle) object, eventCount);
        eventCount++;
        cleanUpEvents();
        events.notifyAll();
      }
    }
  }

  /**
   * Provides a list of events within the given range, waiting at most <code>timeout</code>
   * milliseconds for new events if there currently aren't any.
   *
   * @param minSequenceNo The minimum sequence number for accepted events.
   * @param maxSequenceNo The maximum sequence number for accepted events.
   * @param timeout The maximum time to wait for events (in ms) if there currently aren't any.
   * @return A list of events within the given range.
   */
  public StatusMessageList fetchEvents(long minSequenceNo, long maxSequenceNo, long timeout)
      throws IllegalArgumentException {
    checkInRange(minSequenceNo, 0, Long.MAX_VALUE, "minSequenceNo");
    checkInRange(maxSequenceNo, minSequenceNo, Long.MAX_VALUE, "maxSequenceNo");
    checkInRange(timeout, 0, Long.MAX_VALUE, "timeout");

    StatusMessageList result = new StatusMessageList();
    synchronized (events) {
      Collection<StatusMessage> messages = events.subMap(minSequenceNo, maxSequenceNo).values();
      if (messages.isEmpty()) {
        try {
          events.wait(timeout);
        }
        catch (InterruptedException exc) {
          LOG.warn("Unexpectedly interrupted", exc);
        }
      }
      messages = events.subMap(minSequenceNo, maxSequenceNo).values();
      result.getStatusMessages().addAll(messages);
    }
    return result;
  }

  private void addOrderStatusMessage(TransportOrder order, long sequenceNumber) {
    events.put(sequenceNumber, OrderStatusMessage.fromTransportOrder(order, sequenceNumber));
  }

  private void addVehicleStatusMessage(Vehicle vehicle, long sequenceNumber) {
    events.put(sequenceNumber, VehicleStatusMessage.fromVehicle(vehicle, sequenceNumber));
  }

  private void cleanUpEvents() {
    // XXX Sanitize maxEventCount
    int maxEventCount = configuration.statusEventsCapacity();
    while (events.size() > maxEventCount) {
      events.remove(events.firstKey());
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/CandidateComparatorByVehicleNameTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.Route;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;
import org.opentcs.strategies.basic.dispatching.priorization.candidate.CandidateComparatorByVehicleName;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorByVehicleNameTest {

  private CandidateComparatorByVehicleName comparator;

  @Before
  public void setUp() {
    comparator = new CandidateComparatorByVehicleName();
  }

  @Test
  public void sortVehicleNamesAlphabetically() {
    AssignmentCandidate candidate1 = candidateWithVehicleName("AA");
    AssignmentCandidate candidate2 = candidateWithVehicleName("C");
    AssignmentCandidate candidate3 = candidateWithVehicleName("AB");

    List<AssignmentCandidate> list = new ArrayList<>();
    list.add(candidate1);
    list.add(candidate2);
    list.add(candidate3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(candidate1)));
    assertThat(list.get(1), is(theInstance(candidate3)));
    assertThat(list.get(2), is(theInstance(candidate2)));
  }

  private AssignmentCandidate candidateWithVehicleName(String vehicleName) {
    TransportOrder trasportOrder = new TransportOrder("TOrder1", new ArrayList<>());
    Route.Step dummyStep
        = new Route.Step(null, null, new Point("Point1"), Vehicle.Orientation.FORWARD, 1);
    Route route = new Route(Arrays.asList(dummyStep), 10);
    List<DriveOrder> driveOrders = new LinkedList<>();
    driveOrders.add(new DriveOrder(new DriveOrder.Destination(new Point("Point2").getReference()))
        .withRoute(route));

    return new AssignmentCandidate(new Vehicle(vehicleName), trasportOrder, driveOrders);
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/util/TextAreaDialog.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import java.util.Collection;
import java.util.LinkedList;
import static java.util.Objects.requireNonNull;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.UIManager;

/**
 * Shows a dialog with a text area and a label to describe the content of it.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TextAreaDialog
    extends JDialog {

  private Collection<String> contents;

  /**
   * Creates new form TextAreaDialog.
   *
   * @param parent the parent of this dialog
   * @param modal specifies whether dialog blocks user input to other top-level windows when shown
   * @param description the description of the text area content
   */
  public TextAreaDialog(java.awt.Component parent, boolean modal, String description) {
    super(JOptionPane.getFrameForComponent(parent), modal);
    initComponents();
    textAreaLabel.setText(description);
  }

  /**
   * Returns the content of the text area.
   *
   * @return the content of the text area
   */
  public Collection<String> getContent() {
    return new LinkedList<>(contents);
  }

  /**
   * Sets the content of the text area.
   *
   * @param contents the content of the text area
   */
  public void setContent(Collection<String> contents) {
    this.contents = requireNonNull(contents, "contents");

    contentTextArea.setText("");
    contents.stream().map(o -> o + "\n").forEach(contentTextArea::append);
  }

  /**
   * This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    contentPane = new javax.swing.JPanel();
    contentScrollPane = new javax.swing.JScrollPane();
    contentTextArea = new javax.swing.JTextArea();
    textAreaLabel = new javax.swing.JLabel();
    buttonPane = new javax.swing.JPanel();
    okButton = new javax.swing.JButton();
    symbolPane = new javax.swing.JPanel();
    symbolLabel = new javax.swing.JLabel();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setResizable(false);

    contentPane.setPreferredSize(new java.awt.Dimension(300, 150));
    contentPane.setLayout(new java.awt.BorderLayout());

    contentTextArea.setEditable(false);
    contentTextArea.setColumns(20);
    contentTextArea.setRows(5);
    contentScrollPane.setViewportView(contentTextArea);

    contentPane.add(contentScrollPane, java.awt.BorderLayout.CENTER);

    textAreaLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    textAreaLabel.setText(" ");
    contentPane.add(textAreaLabel, java.awt.BorderLayout.NORTH);

    getContentPane().add(contentPane, java.awt.BorderLayout.CENTER);

    buttonPane.setLayout(new java.awt.GridBagLayout());

    okButton.setText("OK");
    okButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        okButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    buttonPane.add(okButton, gridBagConstraints);

    getContentPane().add(buttonPane, java.awt.BorderLayout.SOUTH);

    symbolPane.setPreferredSize(new java.awt.Dimension(100, 100));
    symbolPane.setLayout(new java.awt.GridBagLayout());

    symbolLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
    symbolLabel.setPreferredSize(new java.awt.Dimension(32, 32));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
    symbolPane.add(symbolLabel, gridBagConstraints);

    getContentPane().add(symbolPane, java.awt.BorderLayout.WEST);

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
    setVisible(false);
  }//GEN-LAST:event_okButtonActionPerformed

  // CHECKSTYLE:OFF
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel buttonPane;
  private javax.swing.JPanel contentPane;
  private javax.swing.JScrollPane contentScrollPane;
  private javax.swing.JTextArea contentTextArea;
  private javax.swing.JButton okButton;
  private javax.swing.JLabel symbolLabel;
  private javax.swing.JPanel symbolPane;
  private javax.swing.JLabel textAreaLabel;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/action/actions/CreatePeripheralJobAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.actions;

import java.awt.Component;
import java.awt.event.ActionEvent;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.swing.AbstractAction;
import static javax.swing.Action.MNEMONIC_KEY;
import static javax.swing.Action.NAME;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.access.to.peripherals.PeripheralJobCreationTO;
import org.opentcs.customizations.plantoverview.ApplicationFrame;
import org.opentcs.guing.components.dialogs.StandardContentDialog;
import org.opentcs.guing.transport.CreatePeripheralJobPanel;
import static org.opentcs.guing.util.I18nPlantOverviewOperating.MENU_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An action to trigger the creation of a peripheral job.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CreatePeripheralJobAction
    extends AbstractAction {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(CreatePeripheralJobAction.class);
  /**
   * This action class's ID.
   */
  public static final String ID = "actions.createPeripheralJob";
  /**
   * Access to the resource bundle.
   */
  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
  /**
   * The parent component for dialogs show by this action.
   */
  private final Component dialogParent;
  /**
   * Provides panels for entering a new peripheral job.
   */
  private final Provider<CreatePeripheralJobPanel> jobPanelProvider;
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;

  /**
   * Creates a new instance.
   *
   * @param dialogParent The parent for dialogs shown by this action.
   * @param peripheralJobPanel Provides panels for entering new peripheral jobs.
   * @param portalProvider Provides access to the kernel service portal.
   */
  @Inject
  public CreatePeripheralJobAction(@ApplicationFrame Component dialogParent,
                                   Provider<CreatePeripheralJobPanel> peripheralJobPanel,
                                   SharedKernelServicePortalProvider portalProvider) {
    this.dialogParent = requireNonNull(dialogParent, "dialogParent");
    this.jobPanelProvider = requireNonNull(peripheralJobPanel, "peripheralJobPanel");
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");

    putValue(NAME, BUNDLE.getString("createPeripheralJobAction.name"));
    putValue(MNEMONIC_KEY, Integer.valueOf('P'));
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    CreatePeripheralJobPanel contentPanel = jobPanelProvider.get();
    StandardContentDialog dialog = new StandardContentDialog(dialogParent, contentPanel);
    dialog.setVisible(true);

    if (dialog.getReturnStatus() != StandardContentDialog.RET_OK) {
      return;
    }

    PeripheralJobCreationTO job
        = new PeripheralJobCreationTO("Job-",
                                      contentPanel.getReservationToken(),
                                      contentPanel.getPeripheralOperation())
            .withIncompleteName(true);

    try (SharedKernelServicePortal sharedPortal = portalProvider.register()) {
      sharedPortal.getPortal().getPeripheralJobService().createPeripheralJob(job);
      sharedPortal.getPortal().getPeripheralDispatcherService().dispatch();
    }
    catch (KernelRuntimeException exception) {
      LOG.warn("Unexpected exception", exception);
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayerEditorModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import org.opentcs.guing.model.DrawnModelComponent;

/**
 * Provides methods to edit layers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface LayerEditorModeling
    extends LayerEditor {

  /**
   * Creates a new layer.
   */
  void createLayer();

  /**
   * Deletes the layer with the given layer ID.
   *
   * @param layerId The ID of the layer to delete.
   * @throws IllegalArgumentException If a layer with the given layer ID doesn't exist.
   */
  void deleteLayer(int layerId)
      throws IllegalArgumentException;

  /**
   * Adds the given model component to the layer that is set in the component's layer wrapper 
   * property.
   *
   * @param modelComponent The model component to add.
   */
  void add(DrawnModelComponent modelComponent);

  /**
   * Removes the given model component from its layer.
   *
   * @param modelComponent The model component to remove.
   */
  void remove(DrawnModelComponent modelComponent);

  /**
   * Moves the layer with the given ID one level down.
   *
   * @param layerId The ID of the layer.
   */
  void moveLayerDown(int layerId);

  /**
   * Moves the layer with the given ID one level up.
   *
   * @param layerId The ID of the layer.
   */
  void moveLayerUp(int layerId);

  /**
   * Sets the layer with the given ID as the active layer.
   *
   * @param layerId The ID of the layer.
   */
  void setLayerActive(int layerId);

  /**
   * Sets the group ID for the layer with the given ID.
   *
   * @param layerId The ID of the layer.
   * @param groupId The ID of the layer group.
   */
  void setLayerGroupId(int layerId, int groupId);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/package-info.java<|end_filename|>
/**
 * Components needed for controlling peripheral devices and processing information sent by them.
 */
package org.opentcs.drivers.peripherals;


<|start_filename|>openTCS-API-Base/src/test/java/org/opentcs/util/AssertionsTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util;

import org.junit.*;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AssertionsTest {
  
  public AssertionsTest() {
  }
  
  @Test
  public void checkArgumentShouldFormatIntegerMessageTemplateArgument() {
    try {
      Assertions.checkArgument(false, "%s", 123);
    }
    catch (IllegalArgumentException exc) {
      Assert.assertEquals("123", exc.getMessage());
    }
  }
  
  @Test
  public void checkInRangeShouldIncludeBoundaries() {
    Assert.assertEquals(22, Assertions.checkInRange(22, 22, 24));
    Assert.assertEquals(23, Assertions.checkInRange(23, 22, 24));
    Assert.assertEquals(24, Assertions.checkInRange(24, 22, 24));
  }

  @Test(expected = IllegalArgumentException.class)
  public void checkInRangeShouldFailOnLessThanMinimum() {
    Assertions.checkInRange(21, 22, 24);
  }

  @Test(expected = IllegalArgumentException.class)
  public void checkInRangeShouldFailOnMoreThanMaximum() {
    Assertions.checkInRange(25, 22, 24);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/peripherals/PeripheralJob.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.peripherals;

import java.io.Serializable;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import static org.opentcs.data.peripherals.PeripheralJobHistoryCodes.JOB_CREATED;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * Represents a job that is to be processed by a peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralJob
    extends TCSObject<PeripheralJob>
    implements Serializable {

  /**
   * A token that may be used to reserve a peripheral device.
   * A peripheral device that is reserved for a specific token can only process jobs which match
   * that reservation token.
   * This string may not be empty.
   */
  @Nonnull
  private final String reservationToken;
  /**
   * The vehicle for which this peripheral job was created.
   * May be {@code null}, if this job wasn't created in the context of a transport order being
   * processed by a vehicle.
   */
  @Nullable
  private final TCSObjectReference<Vehicle> relatedVehicle;
  /**
   * The transport order for which this peripheral job was created.
   * May be {@code null}, if this job wasn't created in the context of a transport order being
   * processed by a vehicle.
   */
  @Nullable
  private final TCSObjectReference<TransportOrder> relatedTransportOrder;
  /**
   * The operation that is to be performed by the pripheral device.
   */
  @Nonnull
  private final PeripheralOperation peripheralOperation;
  /**
   * This peripheral job's current state.
   */
  @Nonnull
  private final State state;
  /**
   * The point of time at which this peripheral job was created.
   */
  @Nonnull
  private final Instant creationTime;
  /**
   * The point of time at which processing of this peripheral job was finished.
   */
  @Nonnull
  private final Instant finishedTime;

  /**
   * Creates a new instance.
   *
   * @param name The peripheral job's name.
   * @param reservationToken The reservation token to be used.
   * @param peripheralOperation The operation to be performed.
   */
  public PeripheralJob(@Nonnull String name,
                       @Nonnull String reservationToken,
                       @Nonnull PeripheralOperation peripheralOperation) {
    this(name,
         new HashMap<>(),
         new ObjectHistory().withEntryAppended(new ObjectHistory.Entry(JOB_CREATED)),
         reservationToken,
         null,
         null,
         peripheralOperation,
         State.TO_BE_PROCESSED,
         Instant.now(),
         Instant.MAX);
  }

  private PeripheralJob(String objectName,
                        Map<String, String> properties,
                        ObjectHistory history,
                        String reservationToken,
                        TCSObjectReference<Vehicle> relatedVehicle,
                        TCSObjectReference<TransportOrder> transportOrder,
                        PeripheralOperation peripheralOperation,
                        State state,
                        Instant creationTime,
                        Instant finishedTime) {
    super(objectName, properties, history);
    this.reservationToken = requireNonNull(reservationToken, "reservationToken");
    checkArgument(!reservationToken.isEmpty(), "reservationToken may not be empty.");
    this.relatedVehicle = relatedVehicle;
    this.relatedTransportOrder = transportOrder;
    this.peripheralOperation = requireNonNull(peripheralOperation, "peripheralOperation");
    this.state = requireNonNull(state, "state");
    this.creationTime = requireNonNull(creationTime, "creationTime");
    this.finishedTime = requireNonNull(finishedTime, "finishedTime");
  }

  @Override
  public PeripheralJob withProperty(String key, String value) {
    return new PeripheralJob(getName(),
                             propertiesWith(key, value),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  @Override
  public PeripheralJob withProperties(Map<String, String> properties) {
    return new PeripheralJob(getName(),
                             properties,
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  @Override
  public PeripheralJob withHistoryEntry(ObjectHistory.Entry entry) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory().withEntryAppended(entry),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  @Override
  public PeripheralJob withHistory(ObjectHistory history) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             history,
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns the token that may be used to reserve a peripheral device.
   *
   * @return The token that may be used to reserve a peripheral device.
   */
  public String getReservationToken() {
    return reservationToken;
  }

  /**
   * Creates a copy of this object, with the given reservation token.
   *
   * @param reservationToken The reservation token to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withReservationToken(String reservationToken) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns the vehicle for which this peripheral job was created.
   *
   * @return The vehicle for which this peripheral job was created.
   */
  public TCSObjectReference<Vehicle> getRelatedVehicle() {
    return relatedVehicle;
  }

  /**
   * Creates a copy of this object, with the given related vehicle.
   *
   * @param relatedVehicle The related vehicle to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withRelatedVehicle(TCSObjectReference<Vehicle> relatedVehicle) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns the transport order for which this peripheral job was created.
   *
   * @return The transport order for which this peripheral job was created.
   */
  public TCSObjectReference<TransportOrder> getRelatedTransportOrder() {
    return relatedTransportOrder;
  }

  /**
   * Creates a copy of this object, with the given related transport order.
   *
   * @param relatedTransportOrder The related transport order to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withRelatedTransportOrder(
      TCSObjectReference<TransportOrder> relatedTransportOrder) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns the operation that is to be performed by the peripheral device.
   *
   * @return The operation that is to be performed by the peripheral device.
   */
  public PeripheralOperation getPeripheralOperation() {
    return peripheralOperation;
  }

  /**
   * Creates a copy of this object, with the given peripheral operation.
   *
   * @param peripheralOperation The peripheral operation to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withPeripheralOperation(PeripheralOperation peripheralOperation) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns this peripheral job's current state.
   *
   * @return this peripheral job's current state.
   */
  public State getState() {
    return state;
  }

  /**
   * Creates a copy of this object, with the given state.
   *
   * @param state The state to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withState(State state) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns the point of time at which this peripheral job was created.
   *
   * @return The point of time at which this peripheral job was created.
   */
  public Instant getCreationTime() {
    return creationTime;
  }

  /**
   * Creates a copy of this object, with the given creation time.
   *
   * @param creationTime The creation time to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withCreationTime(Instant creationTime) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Returns the point of time at which processing of this peripheral job was finished.
   *
   * @return The point of time at which processing of this peripheral job was finished.
   */
  public Instant getFinishedTime() {
    return finishedTime;
  }

  /**
   * Creates a copy of this object, with the given finished time.
   *
   * @param finishedTime The finished time to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralJob withFinishedTime(Instant finishedTime) {
    return new PeripheralJob(getName(),
                             getProperties(),
                             getHistory(),
                             reservationToken,
                             relatedVehicle,
                             relatedTransportOrder,
                             peripheralOperation,
                             state,
                             creationTime,
                             finishedTime);
  }

  /**
   * Defines the various states a peripheral job may be in.
   */
  public static enum State {
    TO_BE_PROCESSED,
    BEING_PROCESSED,
    FINISHED,
    FAILED;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/QueryResponder.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel;

/**
 * A responder for generic queries.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface QueryResponder {

  /**
   * Executes the specified query.
   *
   * @param <T> The query/result type.
   * @param query The query/parameter object.
   * @return The query result.
   */
  <T> T query(Query<T> query);
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/LocationTypeCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.model.visualization.LocationRepresentation;

/**
 * A transfer object describing a location type in the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LocationTypeCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The allowed operations for this location type.
   */
  private List<String> allowedOperations = new LinkedList<>();
  /**
   * The allowed peripheral operations for this location type.
   */
  private List<String> allowedPeripheralOperations = new LinkedList<>();
  /**
   * The information regarding the grahical representation of this location type.
   */
  private Layout layout = new Layout();

  /**
   * Creates a new instance.
   *
   * @param name The name of this location type.
   */
  public LocationTypeCreationTO(@Nonnull String name) {
    super(name);
  }

  private LocationTypeCreationTO(@Nonnull String name,
                                 @Nonnull Map<String, String> properties,
                                 @Nonnull List<String> allowedOperations,
                                 @Nonnull List<String> allowedPeripheralOperations,
                                 @Nonnull Layout layout) {
    super(name, properties);
    this.allowedOperations = requireNonNull(allowedOperations, "allowedOperations");
    this.allowedPeripheralOperations = requireNonNull(allowedPeripheralOperations,
                                                      "allowedPeripheralOperations");
    this.layout = requireNonNull(layout, "layout");
  }

  /**
   * Returns the allowed operations for this location type.
   *
   * @return The allowed operations for this location type.
   */
  @Nonnull
  public List<String> getAllowedOperations() {
    return Collections.unmodifiableList(allowedOperations);
  }

  /**
   * Creates a copy of this object with the given allowed operations.
   *
   * @param allowedOperations the new allowed operations.
   * @return A copy of this object, differing in the given value.
   */
  public LocationTypeCreationTO withAllowedOperations(@Nonnull List<String> allowedOperations) {
    return new LocationTypeCreationTO(getName(),
                                      getModifiableProperties(),
                                      allowedOperations,
                                      allowedPeripheralOperations,
                                      layout);
  }

  /**
   * Returns the allowed peripheral operations for this location type.
   *
   * @return The allowed peripheral operations for this location type.
   */
  @Nonnull
  public List<String> getAllowedPeripheralOperations() {
    return Collections.unmodifiableList(allowedPeripheralOperations);
  }

  /**
   * Creates a copy of this object with the given allowed peripheral operations.
   *
   * @param allowedPeripheralOperations the new allowed peripheral operations.
   * @return A copy of this object, differing in the given value.
   */
  public LocationTypeCreationTO withAllowedPeripheralOperations(
      @Nonnull List<String> allowedPeripheralOperations) {
    return new LocationTypeCreationTO(getName(),
                                      getModifiableProperties(),
                                      allowedOperations,
                                      allowedPeripheralOperations,
                                      layout);
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new name.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public LocationTypeCreationTO withName(@Nonnull String name) {
    return new LocationTypeCreationTO(name,
                                      getProperties(),
                                      allowedOperations,
                                      allowedPeripheralOperations,
                                      layout);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public LocationTypeCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new LocationTypeCreationTO(getName(),
                                      properties,
                                      allowedOperations,
                                      allowedPeripheralOperations,
                                      layout);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public LocationTypeCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new LocationTypeCreationTO(getName(),
                                      propertiesWith(key, value),
                                      allowedOperations,
                                      allowedPeripheralOperations,
                                      layout);
  }

  /**
   * Returns the information regarding the grahical representation of this location type.
   *
   * @return The information regarding the grahical representation of this location type.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public LocationTypeCreationTO withLayout(Layout layout) {
    return new LocationTypeCreationTO(getName(),
                                      getModifiableProperties(),
                                      allowedOperations,
                                      allowedPeripheralOperations,
                                      layout);
  }

  @Override
  public String toString() {
    return "LocationTypeCreationTO{"
        + "name=" + getName()
        + ", allowedOperations=" + allowedOperations
        + ", allowedPeripheralOperations" + allowedPeripheralOperations
        + ", layout=" + layout
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Contains information regarding the grahical representation of a location type.
   */
  public static class Layout
      implements Serializable {

    /**
     * The location representation to use for locations with this location type.
     */
    private final LocationRepresentation locationRepresentation;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(LocationRepresentation.NONE);
    }

    /**
     * Creates a new instance.
     *
     * @param locationRepresentation The location representation to use for locations with this
     * location type.
     */
    public Layout(LocationRepresentation locationRepresentation) {
      this.locationRepresentation = requireNonNull(locationRepresentation,
                                                   "locationRepresentation");
    }

    /**
     * Returns the location representation to use for locations with this location type.
     *
     * @return The location representation to use for locations with this location type.
     */
    public LocationRepresentation getLocationRepresentation() {
      return locationRepresentation;
    }

    /**
     * Creates a copy of this object, with the given location representation.
     *
     * @param locationRepresentation The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLocationRepresentation(LocationRepresentation locationRepresentation) {
      return new Layout(locationRepresentation);
    }

    @Override
    public String toString() {
      return "Layout{"
          + "locationRepresentation=" + locationRepresentation
          + '}';
    }
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/KernelStateShutdown.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.kernel.persistence.ModelPersister;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.TCSObjectPool;

/**
 * This class implements the standard openTCS kernel when it's shut down.
 *
 * @author <NAME> (Fraunhofer IML)
 */
final class KernelStateShutdown
    extends KernelState {

  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  /**
   * Creates a new StandardKernelShutdownState.
   *
   * @param globalSyncObject The kernel threads' global synchronization object
   * @param objectPool The object pool to be used.
   * @param model The model to be used.
   * @param modelPersister The model persister to be used.
   */
  @Inject
  public KernelStateShutdown(@GlobalSyncObject Object globalSyncObject,
                             TCSObjectPool objectPool,
                             Model model,
                             ModelPersister modelPersister) {
    super(globalSyncObject,
          objectPool,
          model,
          modelPersister);
  }

  // Methods that HAVE to be implemented/overridden start here.
  @Override
  public void initialize() {
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    initialized = false;
  }

  @Override
  public Kernel.State getState() {
    return Kernel.State.SHUTDOWN;
  }
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/peripherals/PeripheralTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.peripherals;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralAttachmentInformation;
import static org.opentcs.kernelcontrolcenter.I18nKernelControlCenter.BUNDLE_PATH;
import static org.opentcs.util.Assertions.checkArgument;
import org.opentcs.util.CallWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A model for displaying a table of peripherals.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralTableModel
    extends AbstractTableModel
    implements PropertyChangeListener {

  /**
   * This class's resource bundle.
   */
  private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_PATH);
  /**
   * The index of the column showing the peripheral device's name.
   */
  public static final int COLUMN_LOCATION = 0;
  /**
   * The index of the column showing the associated adapter.
   */
  public static final int COLUMN_ADAPTER = 1;
  /**
   * The index of the column showing the adapter's enabled state.
   */
  public static final int COLUMN_ENABLED = 2;
  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralTableModel.class);
  /**
   * The collumn names for the table header.
   */
  private static final String[] COLUMN_NAMES = new String[]{
    BUNDLE.getString("peripheralTableModel.column_location.headerText"),
    BUNDLE.getString("peripheralTableModel.column_adapter.headerText"),
    BUNDLE.getString("peripheralTableModel.column_enabled.headerText")
  };
  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[]{
    String.class,
    PeripheralCommAdapterDescription.class,
    Boolean.class
  };
  /**
   * The service portal to use for kernel interaction.
   */
  private final KernelServicePortal servicePortal;
  /**
   * The call wrapper to use.
   */
  private final CallWrapper callWrapper;
  /**
   * The entries in the table.
   */
  private final List<LocalPeripheralEntry> entries = new ArrayList<>();

  public PeripheralTableModel(KernelServicePortal servicePortal,
                              CallWrapper callWrapper) {
    this.servicePortal = requireNonNull(servicePortal, "servicePortal");
    this.callWrapper = requireNonNull(callWrapper, "callWrapper");
  }

  public void addData(LocalPeripheralEntry entry) {
    entries.add(entry);
    fireTableRowsInserted(entries.size() - 1, entries.size() - 1);
  }

  public LocalPeripheralEntry getDataAt(int index) {
    checkArgument(index >= 0 && index < entries.size(),
                  "index must be in 0..%d: %d",
                  entries.size(),
                  index);
    return entries.get(index);
  }

  @Override
  public int getRowCount() {
    return entries.size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex >= entries.size()) {
      return null;
    }

    LocalPeripheralEntry entry = entries.get(rowIndex);

    switch (columnIndex) {
      case COLUMN_LOCATION:
        return entry.getProcessModel().getLocation().getName();
      case COLUMN_ADAPTER:
        return entry.getAttachedCommAdapter();
      case COLUMN_ENABLED:
        return entry.getProcessModel().isCommAdapterEnabled();
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    requireNonNull(aValue, "aValue");
    LocalPeripheralEntry entry = entries.get(rowIndex);
    switch (columnIndex) {
      case COLUMN_LOCATION:
        break;
      case COLUMN_ADAPTER:
        break;
      case COLUMN_ENABLED:
        try {
        if ((boolean) aValue) {
          callWrapper.call(
              () -> servicePortal.getPeripheralService().enableCommAdapter(entry.getLocation())
          );
        }
        else {
          callWrapper.call(
              () -> servicePortal.getPeripheralService().disableCommAdapter(entry.getLocation())
          );
        }
      }
      catch (Exception ex) {
        LOG.warn("Error enabling/disabling peripheral comm adapter for {}",
                 entry.getLocation().getName(),
                 ex);
      }
      break;
      default:
        throw new IllegalArgumentException("Invalid column index: " + columnIndex);
    }
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case COLUMN_LOCATION:
        return false;
      case COLUMN_ADAPTER:
        return false;
      case COLUMN_ENABLED:
        return true;
      default:
        return false;
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if (!isRelevantUpdate(evt)) {
      return;
    }

    LocalPeripheralEntry entry = (LocalPeripheralEntry) evt.getSource();
    int index = entries.indexOf(entry);
    SwingUtilities.invokeLater(() -> fireTableRowsUpdated(index, index));

  }

  private boolean isRelevantUpdate(PropertyChangeEvent evt) {
    if (!(evt.getSource() instanceof LocalPeripheralEntry)) {
      return false;
    }

    if (Objects.equals(evt.getPropertyName(),
                       LocalPeripheralEntry.Attribute.ATTACHED_COMM_ADAPTER.name())) {
      PeripheralAttachmentInformation oldInfo = (PeripheralAttachmentInformation) evt.getOldValue();
      PeripheralAttachmentInformation newInfo = (PeripheralAttachmentInformation) evt.getNewValue();
      return !oldInfo.getAttachedCommAdapter().equals(newInfo.getAttachedCommAdapter());
    }
    if (Objects.equals(evt.getPropertyName(),
                       LocalPeripheralEntry.Attribute.PROCESS_MODEL.name())) {
      PeripheralProcessModel oldTo = (PeripheralProcessModel) evt.getOldValue();
      PeripheralProcessModel newTo = (PeripheralProcessModel) evt.getNewValue();
      return oldTo.isCommAdapterEnabled() != newTo.isCommAdapterEnabled();
    }

    return false;
  }
}


<|start_filename|>openTCS-KernelControlCenter/src/guiceConfig/java/org/opentcs/kernelcontrolcenter/DefaultKernelControlCenterInjectionModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter;

import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import java.io.File;
import java.util.List;
import java.util.Locale;
import javax.inject.Singleton;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.SslParameterSet;
import org.opentcs.access.rmi.KernelServicePortalBuilder;
import org.opentcs.access.rmi.factories.NullSocketFactoryProvider;
import org.opentcs.access.rmi.factories.SecureSocketFactoryProvider;
import org.opentcs.access.rmi.factories.SocketFactoryProvider;
import org.opentcs.common.DefaultPortalManager;
import org.opentcs.common.GuestUserCredentials;
import org.opentcs.common.KernelClientApplication;
import org.opentcs.common.PortalManager;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.ApplicationHome;
import org.opentcs.customizations.ConfigurableInjectionModule;
import org.opentcs.customizations.ServiceCallWrapper;
import org.opentcs.kernelcontrolcenter.exchange.DefaultServiceCallWrapper;
import org.opentcs.kernelcontrolcenter.exchange.SslConfiguration;
import org.opentcs.kernelcontrolcenter.util.KernelControlCenterConfiguration;
import org.opentcs.kernelcontrolcenter.vehicles.LocalVehicleEntryPool;
import org.opentcs.util.CallWrapper;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.opentcs.util.event.SimpleEventBus;
import org.opentcs.util.gui.dialog.ConnectionParamSet;
import org.opentcs.virtualvehicle.AdapterPanelComponentsFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Guice module for the openTCS kernel control center application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultKernelControlCenterInjectionModule
    extends ConfigurableInjectionModule {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(DefaultKernelControlCenterInjectionModule.class);

  @Override
  protected void configure() {
    File applicationHome = new File(System.getProperty("opentcs.home", "."));
    bind(File.class)
        .annotatedWith(ApplicationHome.class)
        .toInstance(applicationHome);

    bind(LocalVehicleEntryPool.class)
        .in(Singleton.class);

    bind(KernelClientApplication.class)
        .to(KernelControlCenterApplication.class)
        .in(Singleton.class);

    install(new FactoryModuleBuilder().build(AdapterPanelComponentsFactory.class));

    configureEventBus();
    configureKernelControlCenterDependencies();
    configureExchangeInjectionModules();
  }

  private void configureEventBus() {
    EventBus newEventBus = new SimpleEventBus();
    bind(EventHandler.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(newEventBus);
    bind(EventSource.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(newEventBus);
    bind(EventBus.class)
        .annotatedWith(ApplicationEventBus.class)
        .toInstance(newEventBus);
  }

  private void configureExchangeInjectionModules() {
    bind(PortalManager.class)
        .to(DefaultPortalManager.class)
        .in(Singleton.class);
  }

  private void configureKernelControlCenterDependencies() {
    KernelControlCenterConfiguration configuration
        = getConfigBindingProvider().get(KernelControlCenterConfiguration.PREFIX,
                                         KernelControlCenterConfiguration.class);
    bind(KernelControlCenterConfiguration.class)
        .toInstance(configuration);
    configureKernelControlCenter(configuration);
    configureSocketConnections();

    bind(CallWrapper.class)
        .annotatedWith(ServiceCallWrapper.class)
        .to(DefaultServiceCallWrapper.class)
        .in(Singleton.class);

    bind(new TypeLiteral<List<ConnectionParamSet>>() {
    })
        .toInstance(configuration.connectionBookmarks());
  }

  private void configureSocketConnections() {
    SslConfiguration sslConfiguration = getConfigBindingProvider().get(SslConfiguration.PREFIX,
                                                                       SslConfiguration.class);

    //Create the data object for the ssl configuration
    SslParameterSet sslParamSet = new SslParameterSet(SslParameterSet.DEFAULT_KEYSTORE_TYPE,
                                                      null,
                                                      null,
                                                      new File(sslConfiguration.truststoreFile()),
                                                      sslConfiguration.truststorePassword());
    bind(SslParameterSet.class).toInstance(sslParamSet);

    SocketFactoryProvider socketFactoryProvider;
    if (sslConfiguration.enable()) {
      socketFactoryProvider = new SecureSocketFactoryProvider(sslParamSet);
    }
    else {
      LOG.warn("SSL encryption disabled, connections will not be secured!");
      socketFactoryProvider = new NullSocketFactoryProvider();
    }

    //Bind socket provider to the kernel portal
    bind(KernelServicePortal.class)
        .toInstance(new KernelServicePortalBuilder(GuestUserCredentials.USER,
                                                   GuestUserCredentials.PASSWORD)
            .setSocketFactoryProvider(socketFactoryProvider)
            .build());
  }

  private void configureKernelControlCenter(KernelControlCenterConfiguration configuration) {
    Locale.setDefault(Locale.forLanguageTag(configuration.locale()));

    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException
               | UnsupportedLookAndFeelException ex) {
      LOG.warn("Could not set look-and-feel", ex);
    }
    // Show tooltips for 30 seconds (Default: 4 sec)
    ToolTipManager.sharedInstance().setDismissDelay(30 * 1000);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/exchange/adapter/OpsDeskVehicleAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import java.util.HashSet;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.opentcs.access.CredentialsException;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.guing.exchange.DriveOrderHistory;
import org.opentcs.guing.model.FigureDecorationDetails;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.transport.orders.TransportOrdersContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An adapter for vehicles specific to the Operations Desk application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OpsDeskVehicleAdapter
    extends VehicleAdapter {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(OpsDeskVehicleAdapter.class);

  /**
   * Keeps track of the drive order components of vehicles.
   */
  private final DriveOrderHistory driveOrderHistory;
  /**
   * Maintains a set of all transport orders.
   */
  private final TransportOrdersContainer transportOrdersContainer;

  @Inject
  public OpsDeskVehicleAdapter(DriveOrderHistory driveOrderHistory,
                               @Nonnull TransportOrdersContainer transportOrdersContainer) {
    this.driveOrderHistory = requireNonNull(driveOrderHistory, "driveOrderHistory");
    this.transportOrdersContainer = requireNonNull(transportOrdersContainer,
                                                   "transportOrdersContainer");
  }

  @Override
  protected void updateModelDriveOrder(TCSObjectService objectService,
                                       Vehicle vehicle,
                                       VehicleModel vehicleModel,
                                       SystemModel systemModel)
      throws CredentialsException {
    TransportOrder transportOrder = getTransportOrder(objectService, vehicle.getTransportOrder());

    if (transportOrder != null) {
      Set<FigureDecorationDetails> driveOrderComponents
          = getDriveOrderComponents(transportOrder.getCurrentDriveOrder(),
                                    vehicle.getRouteProgressIndex(),
                                    systemModel);
      for (FigureDecorationDetails component : driveOrderComponents) {
        component.addVehicleModel(vehicleModel);
      }

      Set<FigureDecorationDetails> finishedComponents
          = driveOrderHistory.updateDriveOrderComponents(vehicleModel.getName(),
                                                         driveOrderComponents);
      for (FigureDecorationDetails component : finishedComponents) {
        component.removeVehicleModel(vehicleModel);
      }

      vehicleModel.setCurrentDriveOrderPath(getCurrentDriveOrderPath(transportOrder.getCurrentDriveOrder(),
                                                                     vehicle.getRouteProgressIndex(),
                                                                     systemModel));
      vehicleModel.setDriveOrderDestination(getCurrentDriveOrderDestination(transportOrder.getCurrentDriveOrder(),
                                                                            systemModel));

      vehicleModel.setDriveOrderState(transportOrder.getState());
    }
    else {
      Set<FigureDecorationDetails> finishedComponents
          = driveOrderHistory.updateDriveOrderComponents(vehicleModel.getName(), new HashSet<>());
      for (FigureDecorationDetails component : finishedComponents) {
        component.removeVehicleModel(vehicleModel);
      }
      vehicleModel.setCurrentDriveOrderPath(null);
      vehicleModel.setDriveOrderDestination(null);
    }
  }

  @Nullable
  private TransportOrder getTransportOrder(TCSObjectService objectService,
                                           TCSObjectReference<TransportOrder> ref)
      throws CredentialsException {
    if (ref == null) {
      return null;
    }
    return transportOrdersContainer.getTransportOrder(ref.getName()).orElse(null);
  }

  private PathModel getCurrentDriveOrderPath(@Nullable DriveOrder driveOrder,
                                             int routeProgressIndex,
                                             SystemModel systemModel) {
    if (driveOrder == null) {
      return null;
    }
    return driveOrder.getRoute().getSteps().stream()
        .skip(Math.max(0, routeProgressIndex + 1))
        .map(step -> step.getPath())
        .filter(path -> path != null)
        .findFirst()
        .map(path -> systemModel.getPathModel(path.getName()))
        .orElse(null);
  }

  private PointModel getCurrentDriveOrderDestination(@Nullable DriveOrder driveOrder,
                                                     SystemModel systemModel) {
    if (driveOrder == null) {
      return null;
    }
    return systemModel.getPointModel(driveOrder.getDestination().getDestination().getName());
  }

  private Set<FigureDecorationDetails> getDriveOrderComponents(@Nullable DriveOrder driveOrder,
                                                               int routeProgressIndex,
                                                               SystemModel systemModel) {
    if (driveOrder == null) {
      return new HashSet<>();
    }

    Set<FigureDecorationDetails> result = new HashSet<>();
    driveOrder.getRoute().getSteps().stream()
        .skip(routeProgressIndex + 1)
        .flatMap(step -> Stream.of(step.getPath(), step.getDestinationPoint()))
        .filter(pointOrPath -> pointOrPath != null) // paths may be null
        .forEach(pointOrPath -> {
          if (pointOrPath instanceof Point) {
            result.add(systemModel.getPointModel(pointOrPath.getName()));
          }
          else if (pointOrPath instanceof Path) {
            result.add(systemModel.getPathModel(pointOrPath.getName()));
          }
        });

    TCSObjectReference<?> ref = driveOrder.getDestination().getDestination();
    if (ref.getReferentClass().isAssignableFrom(Location.class)) {
      result.add(systemModel.getLocationModel(ref.getName()));
    }

    return result;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/plantoverview/OrderTypeSuggestions.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.plantoverview;

import java.util.Set;

/**
 * Implementations of this class provide suggestions for transport order types.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OrderTypeSuggestions {

  /**
   * Returns a set of types that can be assigned to a transport order.
   *
   * @return A set of types that can be assigned to a transport order.
   */
  Set<String> getTypeSuggestions();
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/ParkingPositionSupplier.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.Optional;
import javax.annotation.Nonnull;
import org.opentcs.components.Lifecycle;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;

/**
 * A strategy for finding parking positions for vehicles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ParkingPositionSupplier
    extends Lifecycle {

  /**
   * Returns a suitable parking position for the given vehicle.
   *
   * @param vehicle The vehicle to find a parking position for.
   * @return A parking position for the given vehicle, or an empty Optional, if no suitable parking
   * position is available.
   */
  @Nonnull
  Optional<Point> findParkingPosition(@Nonnull Vehicle vehicle);
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/VisualLayoutTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "scaleX", "scaleY", "shapeLayoutElements", "modelLayoutElements",
                      "properties"})
public class VisualLayoutTO
    extends PlantModelElementTO {

  private Float scaleX = 0.0F;
  private Float scaleY = 0.0F;
  private List<ShapeLayoutElement> shapeLayoutElements = new ArrayList<>();
  private List<ModelLayoutElement> modelLayoutElements = new ArrayList<>();

  @XmlAttribute(required = true)
  public Float getScaleX() {
    return scaleX;
  }

  public VisualLayoutTO setScaleX(@Nonnull Float scaleX) {
    requireNonNull(scaleX, "scaleX");
    this.scaleX = scaleX;
    return this;
  }

  @XmlAttribute(required = true)
  public Float getScaleY() {
    return scaleY;
  }

  public VisualLayoutTO setScaleY(@Nonnull Float scaleY) {
    requireNonNull(scaleY, "scaleY");
    this.scaleY = scaleY;
    return this;
  }

  @XmlElement(name = "shapeLayoutElement")
  public List<ShapeLayoutElement> getShapeLayoutElements() {
    return shapeLayoutElements;
  }

  public VisualLayoutTO setShapeLayoutElements(
      @Nonnull List<ShapeLayoutElement> shapeLayoutElements) {
    requireNonNull(shapeLayoutElements, "shapeLayoutElements");
    this.shapeLayoutElements = shapeLayoutElements;
    return this;
  }

  @XmlElement(name = "modelLayoutElement")
  public List<ModelLayoutElement> getModelLayoutElements() {
    return modelLayoutElements;
  }

  public VisualLayoutTO setModelLayoutElements(
      @Nonnull List<ModelLayoutElement> modelLayoutElements) {
    requireNonNull(modelLayoutElements, "modelLayoutElements");
    this.modelLayoutElements = modelLayoutElements;
    return this;
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"layer", "properties"})
  public static class ShapeLayoutElement {

    private Long layer = 0L;
    private List<PropertyTO> properties = new ArrayList<>();

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getLayer() {
      return layer;
    }

    public ShapeLayoutElement setLayer(@Nonnull Long layer) {
      requireNonNull(layer, "layer");
      this.layer = layer;
      return this;
    }

    @XmlElement(name = "property")
    public List<PropertyTO> getProperties() {
      return properties;
    }

    public ShapeLayoutElement setProperties(@Nonnull List<PropertyTO> properties) {
      requireNonNull(properties, "properties");
      this.properties = properties;
      return this;
    }
  }

  @XmlAccessorType(XmlAccessType.PROPERTY)
  @XmlType(propOrder = {"visualizedObjectName", "layer", "properties"})
  public static class ModelLayoutElement {

    private String visualizedObjectName = "";
    private Long layer = 0L;
    private List<PropertyTO> properties = new ArrayList<>();

    @XmlAttribute(required = true)
    public String getVisualizedObjectName() {
      return visualizedObjectName;
    }

    public ModelLayoutElement setVisualizedObjectName(@Nonnull String visualizedObjectName) {
      requireNonNull(visualizedObjectName, "visualizedObjectName");
      this.visualizedObjectName = visualizedObjectName;
      return this;
    }

    @XmlAttribute(required = true)
    @XmlSchemaType(name = "unsignedInt")
    public Long getLayer() {
      return layer;
    }

    public ModelLayoutElement setLayer(@Nonnull Long layer) {
      requireNonNull(layer, "layer");
      this.layer = layer;
      return this;
    }

    @XmlElement(name = "property")
    public List<PropertyTO> getProperties() {
      return properties;
    }

    public ModelLayoutElement setProperties(@Nonnull List<PropertyTO> properties) {
      requireNonNull(properties, "properties");
      this.properties = properties;
      return this;
    }
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/TextInputPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.Objects;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Abstract base class for <code>InputPanels</code> that use text fields for input.
 * The main purpose of this class is to provide an easy to use way to validate
 * text inputs using it's nested class {@link TextInputPanel.TextInputValidator 
 * TextInputValidator}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class TextInputPanel
    extends InputPanel {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(TextInputPanel.class);
  /**
   * Create a new instance of <code>TextInputPanel</code>.
   * @param title The title of this panel.
   */
  public TextInputPanel(String title) {
    super(title);
  }

  /**
   * <p>
   * Mark the input of the specified <code>Document</code> as valid/invalid
   * and send {@link ValidationEvent ValidationEvents} to the attached
   * {@link ValidationListener ValidationListeners}. 
   * The <code>Document</code> should be related to an input component in this
   * panel. 
   * </p>
   * <p>
   * <b>Note</b>:<br>
   * The default implementation just forwards the call to
   * {@link InputPanel#setInputValid(boolean)} without respect to the 
   * <code>Document</code>. Therefore subclasses with multiple Documents
   * should overwrite this method to for example check if <b>all</b> input
   * fields are valid and then decide if 
   * {@link InputPanel#setInputValid(boolean)} should be called or not.
   * </p>
   * @param valid true, if the content of the <code>Document</code> is valid
   * @param doc the <code>Document</code>
   */
  protected void setInputValid(boolean valid, Document doc) {
    setInputValid(valid);
  }

  /**
   * <p>
   * A {@link javax.swing.event.DocumentListener DocumentListener} that can be 
   * used by subclasses of {@link TextInputPanel} to validate input in 
   * {@link javax.swing.JTextField JTextFields} and other Components that
   * use {@link javax.swing.text.Document Documents}.
   * It listens to the DocumentEvents of a 
   * <code>Document</code> and validates the Document's 
   * content against a specified regular expression. Some convenient regular
   * expressions are provided as <code>public static</code> variables. 
   * After validation {@link TextInputPanel#setInputValid(boolean, 
   * javax.swing.text.Document)} is called.
   * </p>
   * <p>
   * <b>Note:</b><br>
   * The, for convenience, provided regular expressions do
   * NOT check whether the given number really fits into the range of the 
   * corresponding data type (e.g. <code>int</code> for <code>REGEX_INT</code>).
   * </p>
   * @see TextInputPanel#setInputValid(boolean, javax.swing.text.Document) 
   */
  public class TextInputValidator
      implements DocumentListener {

    /**
     * Regular expression that accepts a floating point 
     * number of arbitary length.
     * The decimal point and positions after it can be omitted.
     * <p>
     * Examples:
     * </p>
     * <ul>
     * <li>3.0 is valid</li>
     * <li>-3 is valid</li>
     * <li>3. is invalid</li>
     * <li>.3 is invalid</li>
     * </ul>
     */
    public static final String REGEX_FLOAT = "[-+]?[0-9]+(\\.[0-9]+)?";
    /**
     * Regular expression that accepts a positive floating point number of 
     * arbitrary length and 0. 
     */
    public static final String REGEX_FLOAT_POS = "\\+?[0-9]+(\\.[0-9]+)?";
    /**
     * Regular expression that accepts a negative floating point number of 
     * arbitrary length and 0. 
     */
    public static final String REGEX_FLOAT_NEG = "-[0-9]+(\\.[0-9]+)?|0+(\\.0+)?";
    /** 
     * Regular expression that accepts any integer of 
     * arbitrary length.
     */
    public static final String REGEX_INT = "[-+]?[0-9]+";
    /** 
     * Regular expression that accepts any positive integer of arbitrary length
     * and 0.
     */
    public static final String REGEX_INT_POS = "\\+?[0-9]+";
    /** 
     * Regular expression that accepts any negative integer of arbitrary length
     * and 0.
     */
    public static final String REGEX_INT_NEG = "-[0-9]+|0+";
    /**
     * Regular expression that accepts an integer in the interval [0,100].
     */
    public static final String REGEX_INT_RANGE_0_100 = "[0-9]|[1-9][0-9]|100";
    /**
     * Regular expression that accepts anything except an empty (or 
     * whitespace-only) string.
     */
    public static final String REGEX_NOT_EMPTY = ".*\\S.*";
    /**
     * Regular expression to validate the documents text against.
     */
    private final String format;

    /**
     * Create an instance of <code>TextInputValidator</code>.
     * @param format The regular expression to use for validation.
     */
    protected TextInputValidator(String format) {
      this.format = Objects.requireNonNull(format);
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
      validate(e.getDocument());
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
      validate(e.getDocument());
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
      // Do nothing 
    }

    /**
     * Validate the specified <code>Document</code> and set the validation
     * state in the {@link InputPanel} accordingly.
     * @param doc The <code>Document</code> to validate.
     */
    private void validate(Document doc) {
      String text;
      try {
        text = doc.getText(0, doc.getLength());
      }
      catch (BadLocationException e) {
        LOG.warn("Exception retrieving document text", e);
        return;
      }
      setInputValid(text.matches(format), doc);
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/application/action/draw/ApplyAttributesAction.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 * Changed by IML to allow access to ResourceBundle.
 *
 *
 * @(#)ApplyAttributesAction.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.application.action.draw;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import static javax.swing.Action.LARGE_ICON_KEY;
import static javax.swing.Action.SMALL_ICON;
import javax.swing.ImageIcon;
import org.jhotdraw.draw.AttributeKey;
import static org.jhotdraw.draw.AttributeKeys.TEXT;
import static org.jhotdraw.draw.AttributeKeys.TRANSFORM;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.action.AbstractSelectedAction;
import org.jhotdraw.draw.event.FigureSelectionEvent;
import org.jhotdraw.undo.CompositeEdit;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * ApplyAttributesAction.
 *
 * @author <NAME>
 */
public class ApplyAttributesAction
    extends AbstractSelectedAction {

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);

  private Set<AttributeKey<?>> excludedAttributes = new HashSet<>(
      Arrays.asList(new AttributeKey<?>[] {TRANSFORM, TEXT}));

  /**
   * Creates a new instance.
   *
   * @param editor The editor.
   */
  public ApplyAttributesAction(DrawingEditor editor) {
    super(editor);

    putValue(NAME, BUNDLE.getString("applyAttributesAction.name"));
    putValue(SHORT_DESCRIPTION, BUNDLE.getString("applyAttributesAction.shortDescription"));

    ImageIcon icon = ImageDirectory.getImageIcon("/toolbar/view-media-visualization.png");
    putValue(SMALL_ICON, icon);
    putValue(LARGE_ICON_KEY, icon);
    updateEnabledState();
  }

  /**
   * Set of attributes that is excluded when applying default attributes.
   *
   * @param excludedAttributes The set of attributes to be excluded.
   */
  public void setExcludedAttributes(Set<AttributeKey<?>> excludedAttributes) {
    this.excludedAttributes = requireNonNull(excludedAttributes, "excludedAttributes");
  }

  @Override
  public void actionPerformed(java.awt.event.ActionEvent e) {
    applyAttributes();
  }

  @SuppressWarnings("unchecked")
  public void applyAttributes() {
    DrawingEditor editor = getEditor();

    ResourceBundleUtil labels = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.TOOLBAR_PATH);
    CompositeEdit edit = new CompositeEdit(labels.getString("applyAttributesAction.undo.presentationName"));
    DrawingView view = getView();
    view.getDrawing().fireUndoableEditHappened(edit);

    for (Figure figure : view.getSelectedFigures()) {
      figure.willChange();

      for (Map.Entry<AttributeKey, Object> entry : editor.getDefaultAttributes().entrySet()) {
        if (!excludedAttributes.contains(entry.getKey())) {
          figure.set(entry.getKey(), entry.getValue());
        }
      }

      figure.changed();
    }

    view.getDrawing().fireUndoableEditHappened(edit);
  }

  public void selectionChanged(FigureSelectionEvent evt) {
    setEnabled(getView().getSelectionCount() == 1);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/peripherals/PeripheralOperationCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.peripherals;

import java.io.Serializable;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.data.peripherals.PeripheralOperation;

/**
 * A transfer object describing an operation to be performed by a peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralOperationCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The operation to be performed by the peripheral device.
   */
  private final String operation;
  /**
   * The name of the location the peripheral device is associated with.
   */
  @Nonnull
  private final String locationName;
  /**
   * The moment at which this operation is to be performed.
   */
  @Nonnull
  private final PeripheralOperation.ExecutionTrigger executionTrigger;
  /**
   * Whether the completion of this operation is required to allow a vehicle to continue driving.
   */
  private final boolean completionRequired;

  /**
   * Creates a new instance with {@code executionTrigger} set to
   * {@link PeripheralOperation.ExecutionTrigger#BEFORE_MOVEMENT} and {@code completionRequired} set
   * to {@code false}.
   *
   * @param operation The operation to be performed by the peripheral device.
   * @param locationName The name of the location the peripheral device is associated with.
   */
  public PeripheralOperationCreationTO(@Nonnull String operation, @Nonnull String locationName) {
    super("");
    this.operation = requireNonNull(operation, "operation");
    this.locationName = requireNonNull(locationName, "locationName");
    this.executionTrigger = PeripheralOperation.ExecutionTrigger.BEFORE_MOVEMENT;
    this.completionRequired = false;
  }

  private PeripheralOperationCreationTO(
      @Nonnull String name,
      @Nonnull Map<String, String> properties,
      @Nonnull String operation,
      @Nonnull String locationName,
      @Nonnull PeripheralOperation.ExecutionTrigger executionTrigger,
      boolean completionRequired) {
    super(name, properties);
    this.operation = requireNonNull(operation, "operation");
    this.locationName = requireNonNull(locationName, "locationName");
    this.executionTrigger = requireNonNull(executionTrigger, "executionTrigger");
    this.completionRequired = completionRequired;
  }

  @Override
  public PeripheralOperationCreationTO withName(@Nonnull String name) {
    return new PeripheralOperationCreationTO(name,
                                             getModifiableProperties(),
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }

  @Override
  public PeripheralOperationCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new PeripheralOperationCreationTO(getName(),
                                             properties,
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }

  @Override
  public PeripheralOperationCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new PeripheralOperationCreationTO(getName(),
                                             propertiesWith(key, value),
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }

  /**
   * Returns the operation to be performed by the peripheral device.
   *
   * @return The operation to be performed by the peripheral device.
   */
  @Nonnull
  public String getOperation() {
    return operation;
  }

  /**
   * Creates a copy of this object, with the given operation.
   *
   * @param operation The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralOperationCreationTO withOperation(@Nonnull String operation) {
    return new PeripheralOperationCreationTO(getName(),
                                             getModifiableProperties(),
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }

  /**
   * Returns the name of the location the peripheral device is associated with.
   *
   * @return The name of the location the peripheral device is associated with.
   */
  @Nonnull
  public String getLocationName() {
    return locationName;
  }

  /**
   * Creates a copy of this object, with the given location name.
   *
   * @param locationName The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralOperationCreationTO withLocationName(@Nonnull String locationName) {
    return new PeripheralOperationCreationTO(getName(),
                                             getModifiableProperties(),
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }

  /**
   * Returns the moment at which this operation is to be performed.
   *
   * @return The moment at which this operation is to be performed.
   */
  @Nonnull
  public PeripheralOperation.ExecutionTrigger getExecutionTrigger() {
    return executionTrigger;
  }

  /**
   * Creates a copy of this object, with the given execution trigger.
   *
   * @param executionTrigger The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralOperationCreationTO withExecutionTrigger(
      @Nonnull PeripheralOperation.ExecutionTrigger executionTrigger) {
    return new PeripheralOperationCreationTO(getName(),
                                             getModifiableProperties(),
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }

  /**
   * Returns whether the completion of this operation is required to allow a vehicle to continue
   * driving.
   *
   * @return Whether the completion of this operation is required to allow a vehicle to continue
   * driving.
   */
  public boolean isCompletionRequired() {
    return completionRequired;
  }

  /**
   * Creates a copy of this object, with the given completion required flag.
   *
   * @param completionRequired The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralOperationCreationTO withCompletionRequired(boolean completionRequired) {
    return new PeripheralOperationCreationTO(getName(),
                                             getModifiableProperties(),
                                             operation,
                                             locationName,
                                             executionTrigger,
                                             completionRequired);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/thirdparty/jhotdraw/application/OpenTCSSDIApplication.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application;

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.swing.JFrame;
import org.jhotdraw.app.SDIApplication;
import org.jhotdraw.app.View;
import org.opentcs.common.PortalManager;
import static org.opentcs.common.PortalManager.ConnectionState.CONNECTED;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.plantoverview.ApplicationFrame;
import org.opentcs.guing.application.OpenTCSView;
import org.opentcs.guing.application.menus.menubar.ApplicationMenuBar;
import org.opentcs.guing.event.ModelNameChangeEvent;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.guing.util.PlantOverviewOperatingApplicationConfiguration;
import org.opentcs.thirdparty.jhotdraw.application.action.file.CloseFileAction;
import org.opentcs.util.event.EventHandler;
import org.opentcs.util.event.EventSource;
import org.opentcs.util.gui.Icons;

/**
 * The enclosing SDI application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSSDIApplication
    extends SDIApplication
    implements EventHandler {

  private static final ResourceBundle BUNDLE
      = ResourceBundle.getBundle(I18nPlantOverviewOperating.SYSTEM_PATH);
  /**
   * The JFrame in which the OpenTCSView is shown.
   */
  private final JFrame contentFrame;
  /**
   * A provider for the menu bar.
   */
  private final Provider<ApplicationMenuBar> menuBarProvider;
  /**
   * Provides the current system model.
   */
  private final ModelManager modelManager;
  /**
   * The application's configuration.
   */
  private final PlantOverviewOperatingApplicationConfiguration appConfig;
  /**
   * Where we register for application events.
   */
  private final EventSource eventSource;
  /**
   * The portal manager.
   */
  private final PortalManager portalManager;

  /**
   * Creates a new instance.
   *
   * @param frame The frame in which the OpenTCSView is to be shown.
   * @param menuBarProvider Provides the main application menu bar.
   * @param modelManager Provides the current system model.
   * @param appConfig The application's configuration.
   * @param eventSource Where this instance registers for application events.
   * @param portalManager The portal manager.
   */
  @Inject
  public OpenTCSSDIApplication(@ApplicationFrame JFrame frame,
                               Provider<ApplicationMenuBar> menuBarProvider,
                               ModelManager modelManager,
                               PlantOverviewOperatingApplicationConfiguration appConfig,
                               @ApplicationEventBus EventSource eventSource,
                               PortalManager portalManager) {
    this.contentFrame = requireNonNull(frame, "frame");
    this.menuBarProvider = requireNonNull(menuBarProvider, "menuBarProvider");
    this.modelManager = requireNonNull(modelManager, "modelManager");
    this.appConfig = requireNonNull(appConfig, "appConfig");
    this.eventSource = requireNonNull(eventSource, "eventSource");
    this.portalManager = requireNonNull(portalManager, "portalManager");
  }

  @Override
  public void show(final View view) {
    requireNonNull(view, "view");

    if (view.isShowing()) {
      return;
    }
    view.setShowing(true);

    eventSource.subscribe(this);

    final OpenTCSView opentcsView = (OpenTCSView) view;

    setupContentFrame(opentcsView);

    TitleUpdater titleUpdater = new TitleUpdater(opentcsView);
    opentcsView.addPropertyChangeListener(titleUpdater);
    eventSource.subscribe(titleUpdater);

    updateViewTitle(view, contentFrame);

    // The frame should be shown only after the view has been initialized.
    opentcsView.start();
    contentFrame.setVisible(true);
  }

  @Override
  protected void updateViewTitle(View view, JFrame frame) {
    ((OpenTCSView) view).updateModelName();
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof ModelNameChangeEvent) {
      ModelNameChangeEvent modelNameChangeEvent = (ModelNameChangeEvent) event;
      updateViewTitle((OpenTCSView) modelNameChangeEvent.getSource(), contentFrame);
    }
  }

  private void updateViewTitle(OpenTCSView view, JFrame frame) {
    String modelName = modelManager.getModel().getName();
    if (view.hasUnsavedChanges()) {
      modelName += "*";
    }

    if (frame != null) {
      frame.setTitle(OpenTCSView.NAME + " - \""
          + modelName + "\" - "
          + BUNDLE.getString("openTcsSdiApplication.frameTitle_connectedTo.text") + portalManager.getDescription()
          + " (" + portalManager.getHost() + ":" + portalManager.getPort() + ")");
    }
  }

  private void setupContentFrame(OpenTCSView opentcsView) {
    contentFrame.setJMenuBar(menuBarProvider.get());

    contentFrame.setIconImages(Icons.getOpenTCSIcons());
    contentFrame.setSize(1024, 768);

    // Restore the window's dimensions from the configuration.
    contentFrame.setExtendedState(appConfig.frameMaximized() ? Frame.MAXIMIZED_BOTH : Frame.NORMAL);

    if (contentFrame.getExtendedState() != Frame.MAXIMIZED_BOTH) {
      contentFrame.setBounds(appConfig.frameBoundsX(),
                             appConfig.frameBoundsY(),
                             appConfig.frameBoundsWidth(),
                             appConfig.frameBoundsHeight());
    }

    contentFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    contentFrame.addWindowListener(new WindowStatusUpdater(opentcsView));
  }

  private class TitleUpdater
      implements PropertyChangeListener,
                 EventHandler {

    private final OpenTCSView opentcsView;

    public TitleUpdater(OpenTCSView opentcsView) {
      this.opentcsView = requireNonNull(opentcsView, "opentcsView");
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
      String name = evt.getPropertyName();

      if (name.equals(View.HAS_UNSAVED_CHANGES_PROPERTY)) {
        updateViewTitle(opentcsView, contentFrame);
      }
    }

    @Override
    public void onEvent(Object event) {
      if (event instanceof PortalManager.ConnectionState) {
        PortalManager.ConnectionState connectionState = (PortalManager.ConnectionState) event;
        switch (connectionState) {
          case CONNECTED:
            break;
          case DISCONNECTED:
            break;
          default:
        }
        updateViewTitle(opentcsView, contentFrame);
      }
    }
  }

  private class WindowStatusUpdater
      extends WindowAdapter {

    private final OpenTCSView opentcsView;

    public WindowStatusUpdater(OpenTCSView opentcsView) {
      this.opentcsView = requireNonNull(opentcsView, "opentcsView");
    }

    @Override
    public void windowClosing(WindowEvent e) {
      // Check if changes to the model still need to be saved.
      getAction(opentcsView, CloseFileAction.ID).actionPerformed(
          new ActionEvent(contentFrame,
                          ActionEvent.ACTION_PERFORMED,
                          CloseFileAction.ID_WINDOW_CLOSING));
    }

    @Override
    public void windowClosed(WindowEvent e) {
      opentcsView.stop();
    }

    @Override
    public void windowGainedFocus(WindowEvent e) {
      setActiveView(opentcsView);
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/package-info.java<|end_filename|>
/**
 * Classes for maintaining the (mainly static) structure and content of openTCS
 * course layouts and the attributes and state of vehicles.
 */
package org.opentcs.data.model;


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/peripherals/dispatching/DefaultPeripheralReleaseStrategy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.peripherals.dispatching;

import java.util.Collection;
import java.util.stream.Collectors;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;

/**
 * The default implementation of {@link PeripheralReleaseStrategy}.
 * Selects peripherals to be released by applying the following rules:
 * <ul>
 * <li>A peripheral's state must be {@link PeripheralInformation.State#IDLE}</li>
 * <li>A peripheral's processing state must be {@link PeripheralInformation.ProcState#IDLE}</li>
 * <li>A peripheral's reservation token must be set.</li>
 * </ul>
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPeripheralReleaseStrategy
    implements PeripheralReleaseStrategy {

  @Override
  public Collection<Location> selectPeripheralsToRelease(Collection<Location> locations) {
    return locations.stream()
        .filter(this::idleAndReserved)
        .collect(Collectors.toSet());
  }

  private boolean idleAndReserved(Location location) {
    return processesNoJob(location) && hasReservationToken(location);
  }

  private boolean processesNoJob(Location location) {
    return location.getPeripheralInformation().getProcState()
        == PeripheralInformation.ProcState.IDLE
        && location.getPeripheralInformation().getState()
        == PeripheralInformation.State.IDLE;
  }

  private boolean hasReservationToken(Location location) {
    return location.getPeripheralInformation().getReservationToken() != null;
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/DefaultPeripheralController.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import com.google.inject.assistedinject.Assisted;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.InternalPeripheralService;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralController;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.drivers.peripherals.management.PeripheralProcessModelEvent;
import static org.opentcs.util.Assertions.checkState;
import org.opentcs.util.ExplainedBoolean;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;

/**
 * Realizes a bidirectional connection between the kernel and a comm adapter controlling a
 * peripheral device.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultPeripheralController
    implements PeripheralController,
               EventHandler {

  /**
   * The location representing the peripheral device controlled by this controller/the comm adapter.
   */
  private final TCSResourceReference<Location> location;
  /**
   * The comm adapter controling the peripheral device.
   */
  private final PeripheralCommAdapter commAdapter;
  /**
   * The peripheral service to use.
   */
  private final InternalPeripheralService peripheralService;
  /**
   * The event bus we should register with and send events to.
   */
  private final EventBus eventBus;
  /**
   * Indicates whether this controller is initialized.
   */
  private boolean initialized;

  /**
   * Creates a new DefaultPeripheralController.
   *
   * @param location The location representing the peripheral device.
   * @param commAdapter The comm adapter that controls the peripheral device.
   * @param peripheralService The peripheral service to be used.
   * @param eventBus The event bus to be used.
   */
  @Inject
  public DefaultPeripheralController(@Assisted @Nonnull TCSResourceReference<Location> location,
                                     @Assisted @Nonnull PeripheralCommAdapter commAdapter,
                                     @Nonnull InternalPeripheralService peripheralService,
                                     @Nonnull @ApplicationEventBus EventBus eventBus) {
    this.location = requireNonNull(location, "location");
    this.commAdapter = requireNonNull(commAdapter, "commAdapter");
    this.peripheralService = requireNonNull(peripheralService, "peripheralService");
    this.eventBus = requireNonNull(eventBus, "eventBus");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    eventBus.subscribe(this);

    updatePeripheralState(commAdapter.getProcessModel().getState());

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    updatePeripheralState(PeripheralInformation.State.UNKNOWN);

    eventBus.unsubscribe(this);

    initialized = false;
  }

  @Override
  public void onEvent(Object event) {
    if (!(event instanceof PeripheralProcessModelEvent)) {
      return;
    }

    PeripheralProcessModelEvent processModelEvent = (PeripheralProcessModelEvent) event;
    if (Objects.equals(processModelEvent.getAttributeChanged(),
                       PeripheralProcessModel.Attribute.STATE.name())
        && Objects.equals(processModelEvent.getLocation(), location)) {
      updatePeripheralState(processModelEvent.getProcessModel().getState());
    }
  }

  @Override
  public void process(PeripheralJob job, PeripheralJobCallback callback)
      throws IllegalStateException {
    requireNonNull(job, "job");
    requireNonNull(callback, "callback");

    ExplainedBoolean canProcess = canProcess(job);
    checkState(canProcess.getValue(),
               "%s: Can't process job: %s",
               location.getName(),
               canProcess.getReason());

    commAdapter.process(job, callback);
  }

  @Override
  public ExplainedBoolean canProcess(PeripheralJob job) {
    requireNonNull(job, "job");
    return commAdapter.canProcess(job);
  }

  @Override
  public void sendCommAdapterCommand(PeripheralAdapterCommand command) {
    requireNonNull(command, "command");
    commAdapter.execute(command);
  }

  private void updatePeripheralState(PeripheralInformation.State newState) {
    requireNonNull(newState, "newState");
    peripheralService.updatePeripheralState(location, newState);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/LinkUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import javax.inject.Inject;
import javax.swing.ImageIcon;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.IconToolkit;

/**
 * Represents a link in the TreeView.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class LinkUserObject
    extends FigureUserObject {

  /**
   * Creates a new instance of LinkUserObject
   *
   * @param modelComponent The corresponding data object
   * @param guiManager The gui manager.
   * @param modelManager The model manager
   */
  @Inject
  public LinkUserObject(@Assisted LinkModel modelComponent,
                        GuiManager guiManager,
                        ModelManager modelManager) {
    super(modelComponent, guiManager, modelManager);
  }

  @Override
  public LinkModel getModelComponent() {
    return (LinkModel) super.getModelComponent();
  }

  @Override
  public ImageIcon getIcon() {
    return IconToolkit.instance().createImageIcon("tree/link.18x18.png");
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/customizations/kernel/ActiveInModellingMode.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.customizations.kernel;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

/**
 * Annotation type for binding injectable components meant to be used in modelling mode.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@Qualifier
@Target(value = {ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ActiveInModellingMode {

}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/drawing/DeleteEdit.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Undoes or redoes the "delete" action.
 */
public class DeleteEdit
    extends AbstractUndoableEdit {

  /**
   * The drawing view we're working with.
   */
  private final DrawingView drawingView;
  /**
   * The deleted figures.
   */
  private final ArrayList<Figure> figures = new ArrayList<>();

  /**
   * Creates a new instance.
   *
   * @param drawingView The drawing view the delete happened in.
   * @param figures The deleted figures.
   */
  public DeleteEdit(DrawingView drawingView, List<Figure> figures) {
    this.drawingView = requireNonNull(drawingView, "drawingView");
    this.figures.addAll(figures);
  }

  @Override
  public String getPresentationName() {
    return ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.MENU_PATH).getString("deleteEdit.presentationName");
  }

  @Override
  public void undo() throws CannotUndoException {
    super.undo();
    drawingView.clearSelection();
    for (Figure figure : figures) {
      drawingView.getDrawing().add(figure);
    }
  }

  @Override
  public void redo() throws CannotRedoException {
    super.redo();
    for (Figure figure : figures) {
      drawingView.getDrawing().remove(figure);
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/vehicle/VehicleComparatorIdleFirst.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.vehicle;

import java.util.Comparator;
import org.opentcs.data.model.Vehicle;

/**
 * Compares {@link Vehicle}s by their states, ordering IDLE vehicles first.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleComparatorIdleFirst
    implements Comparator<Vehicle> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "IDLE_FIRST";

  /**
   * Compares two vehicles by their state.
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param vehicle1 The first vehicle.
   * @param vehicle2 The second vehicle.
   * @return The value zero if vehicle1 and vehicle2 have the same state;
   * a value grater zero, if the state of vehicle1 is idle, unlike vehicle2;
   * a value less than zero otherwise.
   */
  @Override
  public int compare(Vehicle vehicle1, Vehicle vehicle2) {
    if (vehicle1.getState() == vehicle2.getState()) {
      return 0;
    }
    else if (vehicle1.getState() == Vehicle.State.IDLE) {
      return -1;
    }
    else {
      return 1;
    }
  }

}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/recharging/DefaultRechargePositionSupplier.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.recharging;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static org.opentcs.components.kernel.Dispatcher.PROPKEY_ASSIGNED_RECHARGE_LOCATION;
import static org.opentcs.components.kernel.Dispatcher.PROPKEY_PREFERRED_RECHARGE_LOCATION;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.DriveOrder;

/**
 * Finds assigned, preferred or (routing-wise) cheapest recharge locations for vehicles.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultRechargePositionSupplier
    implements RechargePositionSupplier {

  /**
   * The plant model service.
   */
  private final InternalPlantModelService plantModelService;
  /**
   * Our router.
   */
  private final Router router;
  /**
   * Indicates whether this component is enabled.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param plantModelService The plant model service.
   * @param router The router to use.
   */
  @Inject
  public DefaultRechargePositionSupplier(InternalPlantModelService plantModelService,
                                         Router router) {
    this.plantModelService = requireNonNull(plantModelService, "plantModelService");
    this.router = requireNonNull(router, "router");
  }

  @Override
  public void initialize() {
    if (initialized) {
      return;
    }

    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!initialized) {
      return;
    }

    initialized = false;
  }

  @Override
  public List<DriveOrder.Destination> findRechargeSequence(Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");

    if (vehicle.getCurrentPosition() == null) {
      return new ArrayList<>();
    }

    Map<Location, Set<Point>> rechargeLocations
        = findLocationsForOperation(vehicle.getRechargeOperation(),
                                    vehicle,
                                    router.getTargetedPoints());

    String assignedRechargeLocationName = vehicle.getProperty(PROPKEY_ASSIGNED_RECHARGE_LOCATION);
    if (assignedRechargeLocationName != null) {
      Location location = pickLocationWithName(assignedRechargeLocationName,
                                               rechargeLocations.keySet());
      if (location == null) {
        return new ArrayList<>();
      }
      // XXX Strictly, we should check whether there is a viable route to the location.
      return Arrays.asList(createDestination(location, vehicle.getRechargeOperation()));
    }

    String preferredRechargeLocationName = vehicle.getProperty(PROPKEY_PREFERRED_RECHARGE_LOCATION);
    if (assignedRechargeLocationName != null) {
      Location location = pickLocationWithName(preferredRechargeLocationName,
                                               rechargeLocations.keySet());
      if (location != null) {
        // XXX Strictly, we should check whether there is a viable route to the location.
        return Arrays.asList(createDestination(location, vehicle.getRechargeOperation()));
      }
    }

    Location bestLocation = findCheapestLocation(rechargeLocations, vehicle);
    if (bestLocation != null) {
      return Arrays.asList(createDestination(bestLocation, vehicle.getRechargeOperation()));
    }

    return new ArrayList<>();
  }

  @Nullable
  private Location findCheapestLocation(Map<Location, Set<Point>> locations, Vehicle vehicle) {
    Point curPos = plantModelService.fetchObject(Point.class, vehicle.getCurrentPosition());

    return locations.entrySet().stream()
        .map(entry -> bestAccessPointCandidate(vehicle, curPos, entry.getKey(), entry.getValue()))
        .filter(candidate -> candidate.isPresent())
        .map(candidate -> candidate.get())
        .min(Comparator.comparingLong(candidate -> candidate.costs))
        .map(candidate -> candidate.location)
        .orElse(null);
  }

  private DriveOrder.Destination createDestination(Location location, String operation) {
    return new DriveOrder.Destination(location.getReference())
        .withOperation(operation);
  }

  @Nullable
  private Location pickLocationWithName(String name, Set<Location> locations) {
    return locations.stream()
        .filter(location -> name.equals(location.getName()))
        .findAny()
        .orElse(null);
  }

  /**
   * Finds locations allowing the given operation, and the points they would be accessible from for
   * the given vehicle.
   *
   * @param operation The operation.
   * @param vehicle The vehicle.
   * @param targetedPoints The points that are currently targeted by vehicles.
   * @return The locations allowing the given operation, and the points they would be accessible
   * from.
   */
  private Map<Location, Set<Point>> findLocationsForOperation(String operation,
                                                              Vehicle vehicle,
                                                              Set<Point> targetedPoints) {
    Map<Location, Set<Point>> result = new HashMap<>();

    for (Location curLoc : plantModelService.fetchObjects(Location.class)) {
      LocationType lType = plantModelService.fetchObject(LocationType.class, curLoc.getType());
      if (lType.isAllowedOperation(operation)) {
        Set<Point> points = findUnoccupiedAccessPointsForOperation(curLoc,
                                                                   operation,
                                                                   vehicle,
                                                                   targetedPoints);
        if (!points.isEmpty()) {
          result.put(curLoc, points);
        }
      }
    }

    return result;
  }

  private Set<Point> findUnoccupiedAccessPointsForOperation(Location location,
                                                            String rechargeOp,
                                                            Vehicle vehicle,
                                                            Set<Point> targetedPoints) {
    return location.getAttachedLinks().stream()
        .filter(link -> allowsOperation(link, rechargeOp))
        .map(link -> plantModelService.fetchObject(Point.class, link.getPoint()))
        .filter(accessPoint -> isPointUnoccupiedFor(accessPoint, vehicle, targetedPoints))
        .collect(Collectors.toSet());
  }

  /**
   * Checks if the given link either does not define any allowed operations at all (meaning it does
   * not override the allowed operations of the corresponding location's location type), or - if it
   * does - explicitly allows the required recharge operation.
   *
   * @param link The link to be checked.
   * @param operation The operation to be checked for.
   * @return <code>true</code> if, and only if, the given link does not disallow the given
   * operation.
   */
  private boolean allowsOperation(Location.Link link, String operation) {
    // This link is only interesting if it either does not define any allowed operations (does 
    // not override the allowed operations of the corresponding location) at all or, if it does, 
    // allows the required recharge operation.
    return link.getAllowedOperations().isEmpty() || link.hasAllowedOperation(operation);
  }

  private Optional<LocationCandidate> bestAccessPointCandidate(Vehicle vehicle,
                                                               Point srcPosition,
                                                               Location location,
                                                               Set<Point> destPositions) {
    return destPositions.stream()
        .map(point -> new LocationCandidate(location,
                                            router.getCostsByPointRef(vehicle,
                                                                      srcPosition.getReference(),
                                                                      point.getReference())))
        .min(Comparator.comparingLong(candidate -> candidate.costs));
  }

  /**
   * Checks if ALL points within the same block as the given access point are NOT occupied or
   * targeted by any other vehicle than the given one.
   *
   * @param accessPoint The point to be checked.
   * @param vehicle The vehicle to be checked for.
   * @param targetedPoints All currently known targeted points.
   * @return <code>true</code> if, and only if, ALL points within the same block as the given access
   * point are NOT occupied or targeted by any other vehicle than the given one.
   */
  private boolean isPointUnoccupiedFor(Point accessPoint,
                                       Vehicle vehicle,
                                       Set<Point> targetedPoints) {
    return expandPoints(accessPoint).stream()
        .allMatch(point -> !pointOccupiedOrTargetedByOtherVehicle(point,
                                                                  vehicle,
                                                                  targetedPoints));
  }

  private boolean pointOccupiedOrTargetedByOtherVehicle(Point pointToCheck,
                                                        Vehicle vehicle,
                                                        Set<Point> targetedPoints) {
    if (pointToCheck.getOccupyingVehicle() != null
        && !pointToCheck.getOccupyingVehicle().equals(vehicle.getReference())) {
      return true;
    }
    else if (targetedPoints.contains(pointToCheck)) {
      return true;
    }
    return false;
  }

  /**
   * Gathers a set of all points from all blocks that the given point is a member of.
   *
   * @param point The point to check.
   * @return A set of all points from all blocks that the given point is a member of.
   */
  private Set<Point> expandPoints(Point point) {
    return plantModelService.expandResources(Collections.singleton(point.getReference())).stream()
        .filter(resource -> Point.class.equals(resource.getReference().getReferentClass()))
        .map(resource -> (Point) resource)
        .collect(Collectors.toSet());
  }

  private static class LocationCandidate {

    private final Location location;
    private final long costs;

    public LocationCandidate(Location location, long costs) {
      this.location = location;
      this.costs = costs;
    }
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/thirdparty/jhotdraw/application/toolbar/OpenTCSConnectionTool.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 */
package org.opentcs.thirdparty.jhotdraw.application.toolbar;

import com.google.inject.assistedinject.Assisted;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JOptionPane;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import org.jhotdraw.draw.ConnectionFigure;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.tool.ConnectionTool;
import org.opentcs.guing.components.drawing.figures.FigureConstants;
import org.opentcs.guing.components.drawing.figures.LabeledLocationFigure;
import org.opentcs.guing.components.drawing.figures.LinkConnection;
import org.opentcs.guing.components.drawing.figures.ModelBasedFigure;
import org.opentcs.guing.components.drawing.figures.SimpleLineConnection;
import org.opentcs.guing.components.layer.ActiveLayerProvider;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.model.AbstractConnectableModelComponent;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.TOOLBAR_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * A tool to connect two figures with a path for instance.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSConnectionTool
    extends ConnectionTool {

  /**
   * The resource bundle to use.
   */
  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(TOOLBAR_PATH);
  /**
   * Provides the currently active layer.
   */
  private final ActiveLayerProvider activeLayerProvider;
  /**
   * A localized name for this tool. The presentationName is displayed by the
   * UndoableEdit.
   */
  private final String presentationName;

  /**
   * Creates a new instance.
   *
   * @param activeLayerProvider Provides the currently active layer.
   * @param prototype The prototypical figure to be used.
   */
  @Inject
  public OpenTCSConnectionTool(ActiveLayerProvider activeLayerProvider,
                               @Assisted ConnectionFigure prototype) {
    super(prototype);
    this.activeLayerProvider = requireNonNull(activeLayerProvider, "activeLayerProvider");
    presentationName = BUNDLE.getString("openTcsConnectionTool.undo.presentationName");
  }

  @Override
  public void mousePressed(MouseEvent evt) {
    if (!activeLayerProvider.getActiveLayer().getLayer().isVisible()
        || !activeLayerProvider.getActiveLayer().getLayer().isVisible()) {
      JOptionPane.showMessageDialog(
          evt.getComponent(),
          BUNDLE.getString("openTcsConnectionTool.optionPane_activeLayerNotVisible.message"),
          BUNDLE.getString("openTcsConnectionTool.optionPane_activeLayerNotVisible.title"),
          JOptionPane.INFORMATION_MESSAGE
      );
      return;
    }

    super.mousePressed(evt);
  }

  @Override // ConnectionTool
  public void mouseReleased(MouseEvent event) {
    if (!isValidConnection()) {
      removeCreatedFigure();
      return;
    }

    createdFigure.willChange();
    createdFigure.setStartConnector(startConnector);
    createdFigure.setEndConnector(endConnector);
    if (createdFigure instanceof SimpleLineConnection) {
      ((SimpleLineConnection) createdFigure).getModel().updateName();
    }

    createdFigure.changed();

    final Figure addedFigure = createdFigure;
    final Drawing addedDrawing = getDrawing();

    getDrawing().fireUndoableEditHappened(new AbstractUndoableEdit() {

      @Override
      public String getPresentationName() {
        return presentationName;
      }

      @Override
      public void undo()
          throws CannotUndoException {
        super.undo();
        addedDrawing.remove(addedFigure);
      }

      @Override
      public void redo()
          throws CannotRedoException {
        super.redo();
        addedDrawing.add(addedFigure);
      }
    });

    targetFigure = null;
    Point2D.Double cAnchor = startConnector.getAnchor();
    Rectangle r = new Rectangle(getView().drawingToView(cAnchor));
    r.grow(getAnchorWidth(), getAnchorWidth());
    fireAreaInvalidated(r);
    cAnchor = endConnector.getAnchor();
    r = new Rectangle(getView().drawingToView(cAnchor));
    r.grow(getAnchorWidth(), getAnchorWidth());
    fireAreaInvalidated(r);
    startConnector = null;
    endConnector = null;
    Figure finishedFigure = createdFigure;
    createdFigure = null;
    creationFinished(finishedFigure);
  }

  @Override
  protected ConnectionFigure createFigure() {
    ConnectionFigure figure = super.createFigure();

    if (figure instanceof ModelBasedFigure) {
      if (figure instanceof LinkConnection) {
        // Rather than using the active layer for links as well, get the location's layer instead.
        LayerWrapper locationLayer
            = ((LabeledLocationFigure) startConnector.getOwner()).getPresentationFigure().getModel()
                .getPropertyLayerWrapper().getValue();
        ((ModelBasedFigure) figure).getModel().getPropertyLayerWrapper().setValue(locationLayer);
      }
      else {
        ((ModelBasedFigure) figure).getModel()
            .getPropertyLayerWrapper().setValue(activeLayerProvider.getActiveLayer());
      }
    }

    return figure;
  }

  private void removeCreatedFigure() {
    if (createdFigure != null) {
      getDrawing().remove(createdFigure);
      // TODO: Also remove figure from the model

      Point2D.Double cAnchor = startConnector.getAnchor();
      Rectangle r = new Rectangle(getView().drawingToView(cAnchor));
      r.grow(getAnchorWidth(), getAnchorWidth());
      fireAreaInvalidated(r);
      r = new Rectangle(getView().drawingToView(cAnchor));
      r.grow(getAnchorWidth(), getAnchorWidth());
      fireAreaInvalidated(r);
      startConnector = null;
      endConnector = null;
      createdFigure = null;
    }

    if (isToolDoneAfterCreation()) {
      fireToolDone();
    }
  }

  private boolean isValidConnection() {
    // Prevent the manual creation of multiple connections with the same start and end connector.
    return canConnect() && !connectionAlreadyPresent();
  }

  private boolean connectionAlreadyPresent() {
    AbstractConnectableModelComponent startComponent
        = (AbstractConnectableModelComponent) startConnector.getOwner().get(FigureConstants.MODEL);
    AbstractConnectableModelComponent endComponent
        = (AbstractConnectableModelComponent) endConnector.getOwner().get(FigureConstants.MODEL);

    return startComponent != null
        && endComponent != null
        && startComponent.hasConnectionTo(endComponent);
  }

  private boolean canConnect() {
    return createdFigure != null
        && startConnector != null
        && endConnector != null
        && createdFigure.canConnect(startConnector, endConnector);
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/guiceConfig/java/org/opentcs/commadapter/peripheral/loopback/LoopbackPeripheralKernelModule.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback;

import com.google.inject.assistedinject.FactoryModuleBuilder;
import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Loopback adapter-specific Gucie configuration for the Kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LoopbackPeripheralKernelModule
    extends KernelInjectionModule {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(LoopbackPeripheralKernelModule.class);

  @Override
  protected void configure() {
    VirtualPeripheralConfiguration configuration
        = getConfigBindingProvider().get(VirtualPeripheralConfiguration.PREFIX,
                                         VirtualPeripheralConfiguration.class);

    if (!configuration.enable()) {
      LOG.info("Peripheral loopback driver disabled by configuration.");
      return;
    }

    bind(VirtualPeripheralConfiguration.class)
        .toInstance(configuration);

    install(new FactoryModuleBuilder().build(LoopbackPeripheralAdapterComponentsFactory.class));

    peripheralCommAdaptersBinder().addBinding().to(LoopbackPeripheralCommAdapterFactory.class);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/PrioritizedParkingPositionSupplier.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import static org.opentcs.util.Assertions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A parking position supplier that tries to find the parking position with the highest priority
 * that is unoccupied, not on the current route of any other vehicle and as close as possible to the
 * vehicle's current position.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class PrioritizedParkingPositionSupplier
    extends AbstractParkingPositionSupplier {

  /**
   * This class's Logger.
   */
  private static final Logger LOG
      = LoggerFactory.getLogger(PrioritizedParkingPositionSupplier.class);
  /**
   * A function computing the priority of a parking position.
   */
  private final ParkingPositionToPriorityFunction priorityFunction;

  /**
   * Creates a new instance.
   *
   * @param plantModelService The plant model service.
   * @param router A router for computing travel costs to parking positions.
   * @param priorityFunction A function computing the priority of a parking position.
   */
  @Inject
  public PrioritizedParkingPositionSupplier(InternalPlantModelService plantModelService,
                                            Router router,
                                            ParkingPositionToPriorityFunction priorityFunction) {
    super(plantModelService, router);
    this.priorityFunction = requireNonNull(priorityFunction, "priorityFunction");
  }

  @Override
  public Optional<Point> findParkingPosition(final Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");

    if (vehicle.getCurrentPosition() == null) {
      return Optional.empty();
    }

    int currentPriority = priorityOfCurrentPosition(vehicle);
    Set<Point> parkingPosCandidates = findUsableParkingPositions(vehicle).stream()
        .filter(point -> hasHigherPriorityThan(point, currentPriority))
        .collect(Collectors.toSet());

    if (parkingPosCandidates.isEmpty()) {
      LOG.debug("{}: No parking position candidates found.", vehicle.getName());
      return Optional.empty();
    }

    LOG.debug("{}: Selecting parking position from candidates {}.",
              vehicle.getName(),
              parkingPosCandidates);

    parkingPosCandidates = filterPositionsWithHighestPriority(parkingPosCandidates);
    Point parkingPos = nearestPoint(vehicle, parkingPosCandidates);

    LOG.debug("{}: Selected parking position {}.", vehicle.getName(), parkingPos);

    return Optional.ofNullable(parkingPos);
  }

  private int priorityOfCurrentPosition(Vehicle vehicle) {
    Point currentPos = getPlantModelService().fetchObject(Point.class,
                                                          vehicle.getCurrentPosition());
    return priorityFunction
        .andThen(priority -> priority != null ? priority : Integer.MAX_VALUE)
        .apply(currentPos);
  }

  private boolean hasHigherPriorityThan(Point point, Integer priority) {
    Integer pointPriority = priorityFunction.apply(point);
    if (pointPriority == null) {
      return false;
    }

    return pointPriority < priority;
  }

  private Set<Point> filterPositionsWithHighestPriority(Set<Point> positions) {
    checkArgument(!positions.isEmpty(), "'positions' must not be empty");
    
    Map<Integer, List<Point>> prioritiesToPositions = positions.stream()
        .collect(Collectors.groupingBy(point -> priorityFunction.apply(point)));

    Integer highestPriority = prioritiesToPositions.keySet().stream()
        .reduce(Integer::min)
        .get();
    
    return new HashSet<>(prioritiesToPositions.get(highestPriority));
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/OrderCleanerTask.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import com.google.common.collect.Iterables;
import java.time.Instant;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.function.Predicate;
import javax.inject.Inject;
import org.opentcs.components.kernel.OrderSequenceCleanupApproval;
import org.opentcs.components.kernel.TransportOrderCleanupApproval;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.kernel.workingset.TransportOrderPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A task that periodically removes orders in a final state.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class OrderCleanerTask
    implements Runnable {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(OrderCleanerTask.class);
  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * Keeps all the transport orders.
   */
  private final TransportOrderPool orderPool;
  /**
   * Check whether transport orders may be removed.
   */
  private final Set<TransportOrderCleanupApproval> orderCleanupApprovals;
  /**
   * Check whether order sequences may be removed.
   */
  private final Set<OrderSequenceCleanupApproval> sequenceCleanupApprovals;
  /**
   * This class's configuration.
   */
  private final OrderPoolConfiguration configuration;

  /**
   * Creates a new instance.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param orderPool The transport order pool to be used.
   * @param orderCleanupApprovals The set of order cleanup approvals to use.
   * @param sequenceCleanupApprovals The set of sequence cleanup approvals to use.
   * @param configuration This class's configuration.
   */
  @Inject
  public OrderCleanerTask(@GlobalSyncObject Object globalSyncObject,
                          TransportOrderPool orderPool,
                          Set<TransportOrderCleanupApproval> orderCleanupApprovals,
                          Set<OrderSequenceCleanupApproval> sequenceCleanupApprovals,
                          OrderPoolConfiguration configuration) {
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.orderPool = requireNonNull(orderPool, "orderPool");
    this.orderCleanupApprovals = requireNonNull(orderCleanupApprovals, "orderCleanupApprovals");
    this.sequenceCleanupApprovals = requireNonNull(sequenceCleanupApprovals,
                                                   "sequenceCleanupApprovals");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  public long getSweepInterval() {
    return configuration.sweepInterval();
  }

  @Override
  public void run() {
    synchronized (globalSyncObject) {
      LOG.debug("Sweeping order pool...");
      // Candidates that are created before this point of time should be removed.
      Instant creationTimeThreshold = Instant.now().minusMillis(configuration.sweepAge());

      // Remove all transport orders in a final state that do NOT belong to a sequence and that are
      // older than the threshold.
      for (TransportOrder transportOrder
               : orderPool.getObjectPool().getObjects(TransportOrder.class,
                                                      new OrderApproval(creationTimeThreshold))) {
        orderPool.removeTransportOrder(transportOrder.getReference());
      }

      // Remove all order sequences that have been finished, including their transport orders.
      for (OrderSequence orderSequence
               : orderPool.getObjectPool().getObjects(
              OrderSequence.class,
              new SequenceApproval(creationTimeThreshold))) {
        orderPool.removeFinishedOrderSequenceAndOrders(orderSequence.getReference());
      }
    }
  }

  /**
   * Checks whether a transport order may be removed.
   */
  private class OrderApproval
      implements Predicate<TransportOrder> {

    /**
     * Threshold for when a transport order can be removed if it was created before this.
     */
    private final Instant creationTimeThreshold;

    public OrderApproval(Instant creationTimeThreshold) {
      this.creationTimeThreshold = creationTimeThreshold;
    }

    @Override
    public boolean test(TransportOrder order) {
      if (!order.getState().isFinalState()) {
        return false;
      }
      if (order.getWrappingSequence() != null) {
        return false;
      }
      if (order.getCreationTime().isAfter(creationTimeThreshold)) {
        return false;
      }
      for (TransportOrderCleanupApproval approval : orderCleanupApprovals) {
        if (!approval.test(order)) {
          return false;
        }
      }
      return true;
    }
  }

  /**
   * Checks whether an order sequence may be removed.
   */
  private class SequenceApproval
      implements Predicate<OrderSequence> {

    /**
     * Threshold for when a sequence can be removed if it was created before this.
     */
    private final Instant creationTimeThreshold;

    public SequenceApproval(Instant creationTimeThreshold) {
      this.creationTimeThreshold = creationTimeThreshold;
    }

    @Override
    public boolean test(OrderSequence seq) {
      if (!seq.isFinished()) {
        return false;
      }
      List<TCSObjectReference<TransportOrder>> orderRefs = seq.getOrders();
      if (!orderRefs.isEmpty()) {
        TransportOrder lastOrder
            = orderPool.getObjectPool().getObject(TransportOrder.class,
                                                  Iterables.getLast(orderRefs));
        if (lastOrder.getCreationTime().isAfter(creationTimeThreshold)) {
          return false;
        }
      }
      for (OrderSequenceCleanupApproval approval : sequenceCleanupApprovals) {
        if (!approval.test(seq)) {
          return false;
        }
      }
      return true;
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/LayerGroupsProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property that contains a list of layer groups.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerGroupsProperty
    extends AbstractComplexProperty {

  /**
   * Creates a new instance.
   *
   * @param model The model component this property belongs to.
   * @param layerGroups The layer groups.
   */
  public LayerGroupsProperty(ModelComponent model, Map<Integer, LayerGroup> layerGroups) {
    super(model);
    fValue = layerGroups;
  }

  @Override
  public Object getComparableValue() {
    return this.toString();
  }

  @Override
  public String toString() {
    return getValue().values().stream()
        .sorted(Comparator.comparing(group -> group.getId()))
        .map(group -> group.getName())
        .collect(Collectors.joining(", "));
  }

  @Override
  public void copyFrom(Property property) {
    LayerGroupsProperty other = (LayerGroupsProperty) property;
    Map<Integer, LayerGroup> items = new HashMap<>(other.getValue());
    setValue(items);
  }

  @Override
  @SuppressWarnings("unchecked")
  public Map<Integer, LayerGroup> getValue() {
    return (Map) super.getValue();
  }
}


<|start_filename|>openTCS-PlantOverview-Themes-Default/src/main/java/org/opentcs/guing/plugins/themes/StatefulImageVehicleTheme.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.themes;

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;
import java.util.EnumMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.imageio.ImageIO;
import org.opentcs.components.plantoverview.VehicleTheme;
import org.opentcs.data.model.Vehicle;

/**
 * An implementation of <code>VehicleTheme</code> using different images for different vehicle
 * states.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class StatefulImageVehicleTheme
    implements VehicleTheme {

  /**
   * The path containing the images.
   */
  private static final String PATH = "/org/opentcs/guing/plugins/themes/symbols/vehicle/";
  /**
   * The font to be used for labels.
   */
  private static final Font LABEL_FONT = new Font("Arial", Font.BOLD, 12);
  /**
   * Map containing images for a specific vehicle state when it's unloaded.
   */
  private final Map<Vehicle.State, Image> stateMapUnloaded
      = new EnumMap<>(Vehicle.State.class);
  /**
   * Map containing images for a specific vehicle state when it's loaded.
   */
  private final Map<Vehicle.State, Image> stateMapLoaded
      = new EnumMap<>(Vehicle.State.class);

  public StatefulImageVehicleTheme() {
    initMaps();
  }

  @Override
  public Image statelessImage(Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");

    return stateMapUnloaded.get(Vehicle.State.IDLE);
  }

  @Override
  public Image statefulImage(Vehicle vehicle) {
    requireNonNull(vehicle, "vehicle");

    return loaded(vehicle)
        ? stateMapLoaded.get(vehicle.getState())
        : stateMapUnloaded.get(vehicle.getState());
  }

  @Override
  public Font labelFont() {
    return LABEL_FONT;
  }

  @Override
  public Color labelColor() {
    return Color.BLUE;
  }

  @Override
  public int labelOffsetY() {
    return 25;
  }

  @Override
  public int labelOffsetX() {
    return -15;
  }

  @Override
  public String label(Vehicle vehicle) {
    return vehicle.getName();
  }

  /**
   * Initializes the maps with values.
   */
  private void initMaps() {
    stateMapUnloaded.put(Vehicle.State.CHARGING, loadImage(PATH + "unloaded_charging.png"));
    stateMapUnloaded.put(Vehicle.State.ERROR, loadImage(PATH + "unloaded_error.png"));
    stateMapUnloaded.put(Vehicle.State.EXECUTING, loadImage(PATH + "unloaded_normal.png"));
    stateMapUnloaded.put(Vehicle.State.IDLE, loadImage(PATH + "unloaded_normal.png"));
    stateMapUnloaded.put(Vehicle.State.UNAVAILABLE, loadImage(PATH + "unloaded_normal.png"));
    stateMapUnloaded.put(Vehicle.State.UNKNOWN, loadImage(PATH + "unloaded_normal.png"));

    stateMapLoaded.put(Vehicle.State.CHARGING, loadImage(PATH + "loaded_charging.png"));
    stateMapLoaded.put(Vehicle.State.ERROR, loadImage(PATH + "loaded_error.png"));
    stateMapLoaded.put(Vehicle.State.EXECUTING, loadImage(PATH + "loaded_normal.png"));
    stateMapLoaded.put(Vehicle.State.IDLE, loadImage(PATH + "loaded_normal.png"));
    stateMapLoaded.put(Vehicle.State.UNAVAILABLE, loadImage(PATH + "loaded_normal.png"));
    stateMapLoaded.put(Vehicle.State.UNKNOWN, loadImage(PATH + "loaded_normal.png"));
  }

  /**
   * Checks if a given vehicle is loaded.
   *
   * @param vehicle The vehicle.
   * @return Flag indicating if it is loaded.
   */
  private boolean loaded(Vehicle vehicle) {
    return vehicle.getLoadHandlingDevices().stream()
        .anyMatch(lhd -> lhd.isFull());
  }

  /**
   * Loads an image from the file with the given name.
   *
   * @param fileName The name of the file from which to load the image.
   * @return The image.
   */
  private Image loadImage(String fileName) {
    requireNonNull(fileName, "fileName");

    URL url = getClass().getResource(fileName);
    if (url == null) {
      throw new IllegalArgumentException("Invalid image file name " + fileName);
    }
    try {
      return ImageIO.read(url);
    }
    catch (IOException exc) {
      throw new IllegalArgumentException("Exception loading image", exc);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/properties/table/AbstractPropertyCellEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.table;

import java.awt.Color;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Objects;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.opentcs.guing.components.dialogs.DetailsDialog;
import org.opentcs.guing.components.dialogs.DetailsDialogContent;
import org.opentcs.guing.components.dialogs.StandardDetailsDialog;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.util.UserMessageHelper;

/**
 * Base implementation for a cell editor to edit a property.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public abstract class AbstractPropertyCellEditor
    extends javax.swing.DefaultCellEditor {

  /**
   * The color a cell is painted in when a property informs about
   * different values.
   */
  public static final Color DIFFERENT_VALUE_COLOR = new Color(202, 225, 255);
  /**
   * The property.
   */
  protected Property fProperty;
  /**
   * The details dialog that allows editing of the property.
   */
  protected DetailsDialog fDetailsDialog;
  /**
   * The UI component.
   */
  protected final JComponent fComponent;
  /**
   * Utility class to show messages to the user, eg error messages.
   */
  protected final UserMessageHelper userMessageHelper;

  /**
   * Creates a new instance.
   *
   * @param textField
   * @param umh
   */
  public AbstractPropertyCellEditor(JTextField textField, UserMessageHelper umh) {
    super(textField);
    fComponent = createComponent();
    userMessageHelper = Objects.requireNonNull(umh, "umh is null");
  }

  /**
   * Creates a new instance.
   *
   * @param checkBox
   * @param umh
   */
  public AbstractPropertyCellEditor(JCheckBox checkBox, UserMessageHelper umh) {
    super(checkBox);
    fComponent = createComponent();
    userMessageHelper = Objects.requireNonNull(umh, "umh is null");
  }

  /**
   * Creates a new instance.
   *
   * @param comboBox
   * @param umh
   */
  public AbstractPropertyCellEditor(JComboBox<?> comboBox, UserMessageHelper umh) {
    super(comboBox);
    fComponent = createComponent();
    userMessageHelper = Objects.requireNonNull(umh, "umh is null");
  }

  /**
   * Creates the component that edits the property.
   *
   * @return The component that edits the property.
   */
  protected JComponent createComponent() {
    JPanel panel = new JPanel();
    panel.setLayout(new java.awt.BorderLayout());
    panel.add(getComponent(), java.awt.BorderLayout.CENTER);

    JComponent button = createButtonDetailsDialog();

    if (button != null) {
      panel.add(button, java.awt.BorderLayout.EAST);
    }

    return panel;
  }

  /**
   * Creates a button with three dots.
   *
   * @return A button with three dots or null.
   */
  protected JComponent createButtonDetailsDialog() {
    JButton button = new JButton("...");
    button.setMargin(new Insets(0, 2, 0, 2));
    button.addActionListener(new ActionListener() {

      @Override // ActionListener
      public void actionPerformed(ActionEvent e) {
        showDialog();
        fireEditingStopped();
      }
    });

    return button;
  }

  /**
   * Set the dialog that alows for easy edit of the property.
   *
   * @param detailsDialog The dialog that allows editing of the property.
   */
  public void setDetailsDialog(DetailsDialog detailsDialog) {
    fDetailsDialog = detailsDialog;
  }

  /**
   * Set the property.
   *
   * @param value The property.
   */
  protected void setValue(Object value) {
    fProperty = (Property) value;
  }

  /**
   * Mark the property as changed.
   */
  protected void markProperty() {
    fProperty.markChanged();
  }

  /**
   * Opens the dialog.
   */
  protected void showDialog() {
    if (fDetailsDialog != null) {
      DetailsDialogContent content = fDetailsDialog.getDialogContent();
      content.setProperty(fProperty);

      StandardDetailsDialog dialog = (StandardDetailsDialog) fDetailsDialog;
      dialog.setLocationRelativeTo(dialog.getParentComponent());
      dialog.setVisible(true);

      delegate.setValue(fProperty);
      stopCellEditing();
    }
  }

  /**
   * Sets the focus to the actual component (JTextField etc.).
   */
  public void setFocusToComponent() {
    getComponent().requestFocusInWindow();
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/OrderPoolConfiguration.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;

/**
 * Provides methods to configure the {@link OrderCleanerTask}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
@ConfigurationPrefix(OrderPoolConfiguration.PREFIX)
public interface OrderPoolConfiguration {

  /**
   * This configuration's prefix.
   */
  String PREFIX = "orderpool";

  @ConfigurationEntry(
      type = "Long",
      description = "The interval between sweeps (in ms).")
  long sweepInterval();

  @ConfigurationEntry(
      type = "Integer",
      description = "The minimum age of orders to remove in a sweep (in ms).")
  int sweepAge();
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/statistics/StatisticsEvent.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.statistics;

/**
 * Defines labels for events relevant to statistics.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public enum StatisticsEvent {

  /**
   * Indicates a transport order's state has changed to ACTIVE.
   */
  ORDER_ACTIVATED,
  /**
   * Indicates a transport order has been assigned to a vehicle.
   */
  ORDER_ASSIGNED,
  /**
   * Indicates a transport order has been finished successfully.
   */
  ORDER_FINISHED_SUCC,
  /**
   * Indicates a transport order has been finished unsuccessfully.
   */
  ORDER_FINISHED_FAIL,
  /**
   * Indicates an order was processed after its deadline.
   */
  ORDER_CROSSED_DEADLINE,
  /**
   * Indicates a vehicle has started processing an order.
   */
  VEHICLE_STARTS_PROCESSING,
  /**
   * Indicates a vehicle has finished processing an order.
   */
  VEHICLE_STOPS_PROCESSING,
  /**
   * Indicates a vehicle has started recharging its energy source.
   */
  VEHICLE_STARTS_CHARGING,
  /**
   * Indicates a vehicle has stopped recharging its energy source.
   */
  VEHICLE_STOPS_CHARGING,
  /**
   * Indicates a vehicle has started waiting for a resource/command.
   */
  VEHICLE_STARTS_WAITING,
  /**
   * Indicates a vehicle has stopped waiting for a resource/command.
   */
  VEHICLE_STOPS_WAITING,
  /**
   * Indicates a point has been occupied by a vehicle.
   */
  POINT_OCCUPIED,
  /**
   * Indicates a point has no longer been occupied by a vehicle.
   */
  POINT_FREED
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/layer/LayerManagerModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.layer;

import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.jhotdraw.draw.AbstractFigure;
import org.jhotdraw.draw.Drawing;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.data.model.visualization.Layer;
import org.opentcs.data.model.visualization.LayerGroup;
import org.opentcs.guing.application.ViewManager;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.model.DrawnModelComponent;
import org.opentcs.guing.model.ModelComponent;
import static org.opentcs.util.Assertions.checkArgument;
import org.opentcs.util.event.EventBus;

/**
 * The {@link LayerManager} implementation for the model editor application.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerManagerModeling
    extends DefaultLayerManager
    implements LayerEditorModeling,
               LayerGroupEditorModeling,
               ActiveLayerProvider {

  /**
   * The currently active layer.
   */
  private LayerWrapper activeLayerWrapper;

  @Inject
  public LayerManagerModeling(ViewManager viewManager, @ApplicationEventBus EventBus eventBus) {
    super(viewManager, eventBus);
  }

  @Override
  public void createLayer() {
    Layer layer = createLayerWrapper().getLayer();
    getLayerChangeListener().layerAdded();

    setLayerActive(layer.getId());
  }

  @Override
  public void deleteLayer(int layerId)
      throws IllegalArgumentException {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    deleteLayerWrapper(layerId);
    getLayerChangeListener().layerRemoved();

    if (layerId == activeLayerWrapper.getLayer().getId()) {
      handleActiveLayerRemoved();
    }
  }

  @Override
  public void add(DrawnModelComponent modelComponent) {
    int layerId = modelComponent.getPropertyLayerWrapper().getValue().getLayer().getId();
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    addComponent(modelComponent, layerId);
  }

  @Override
  public void remove(DrawnModelComponent modelComponent) {
    removeComponent(modelComponent);
  }

  @Override
  public void moveLayerDown(int layerId) {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    List<LayerWrapper> layerWrappersByOrdinal = getLayerWrappers().values().stream()
        .sorted(Comparator.comparing(wrapper -> wrapper.getLayer().getOrdinal()))
        .collect(Collectors.toList());

    if (layerId == layerWrappersByOrdinal.get(0).getLayer().getId()) {
      // The layer with the given layer ID is already the lowest layer.
      return;
    }

    shiftLayerByOne(layerId, layerWrappersByOrdinal);

    getLayerChangeListener().layersChanged();
  }

  @Override
  public void moveLayerUp(int layerId) {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    List<LayerWrapper> layerWrappersByReverseOrdinal = getLayerWrappers().values().stream()
        .sorted(Comparator.comparing(wrapper -> wrapper.getLayer().getOrdinal(),
                                     Comparator.reverseOrder()))
        .collect(Collectors.toList());

    if (layerId == layerWrappersByReverseOrdinal.get(0).getLayer().getId()) {
      // The layer with the given layer ID is already the heighest layer.
      return;
    }

    shiftLayerByOne(layerId, layerWrappersByReverseOrdinal);

    getLayerChangeListener().layersChanged();
  }

  @Override
  public void setLayerActive(int layerId) {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);

    activeLayerWrapper = getLayerWrapper(layerId);

    getLayerChangeListener().layersChanged();
  }

  @Override
  public void createLayerGroup() {
    int groupId = getNextAvailableLayerGroupId();

    // Add the created layer group to the system model's layout.
    addLayerGroup(new LayerGroup(groupId, "Group " + groupId, true));

    notifyGroupAdded();
  }

  @Override
  public void deleteLayerGroup(int groupId)
      throws IllegalArgumentException {
    checkArgument(getLayerGroup(groupId) != null,
                  "A layer group with layer group ID '%d' doesn't exist.",
                  groupId);

    // Delete the layers that are assigned to the group.
    Set<Integer> layerAssignedToGroup = getLayerWrappers().values().stream()
        .map(wrapper -> wrapper.getLayer())
        .filter(layer -> layer.getGroupId() == groupId)
        .map(layer -> layer.getId())
        .collect(Collectors.toSet());
    layerAssignedToGroup.forEach(layerId -> deleteLayer(layerId));

    removeLayerGroup(groupId);
    notifyGroupRemoved();
  }

  @Override
  public void setLayerGroupId(int layerId, int groupId) {
    checkArgument(getLayerWrapper(layerId) != null,
                  "A layer with layer ID '%d' doesn't exist.",
                  layerId);
    checkArgument(getLayerGroup(groupId) != null,
                  "A layer group with layer group ID '%d' doesn't exist.",
                  groupId);

    LayerWrapper wrapper = getLayerWrapper(layerId);

    boolean visibleBefore = wrapper.getLayer().isVisible() && wrapper.getLayerGroup().isVisible();
    wrapper.setLayer(wrapper.getLayer().withGroupId(groupId));
    wrapper.setLayerGroup(getLayerGroup(groupId));
    boolean visibleAfter = wrapper.getLayer().isVisible() && wrapper.getLayerGroup().isVisible();

    if (visibleBefore != visibleAfter) {
      layerVisibilityChanged(wrapper.getLayer(), visibleAfter);
    }

    getLayerChangeListener().layersChanged();
  }

  @Override
  public LayerWrapper getActiveLayer() {
    return activeLayerWrapper;
  }

  @Override
  protected void reset() {
    super.reset();
  }

  @Override
  protected void restoreLayers() {
    // Make sure there will be one layer set as the active layer. Do it for the highest layer.
    activeLayerWrapper = getLayerWrappers().values().stream()
        .sorted(Comparator.comparing(wrapper -> wrapper.getLayer().getOrdinal(),
                                     Comparator.reverseOrder()))
        .findFirst()
        .get();

    super.restoreLayers();
  }

  private LayerWrapper createLayerWrapper() {
    int layerId = getNextAvailableLayerId();
    int layerOrdinal = getNextAvailableLayerOrdinal();
    LayerGroup group = getLayerGroups().values().iterator().next();
    Layer layer = new Layer(layerId, layerOrdinal, true, "Layer " + layerId, group.getId());
    LayerWrapper wrapper = new LayerWrapper(layer, group);
    getComponents().put(layerId, new HashSet<>());

    // Add the created layer wrapper to the system model's layout.
    addLayerWrapper(wrapper);

    return wrapper;
  }

  private int getNextAvailableLayerId() {
    return getLayerWrappers().values().stream()
        .mapToInt(wrapper -> wrapper.getLayer().getId())
        .max()
        .getAsInt() + 1;
  }

  private int getNextAvailableLayerOrdinal() {
    return getLayerWrappers().values().stream()
        .mapToInt(wrapper -> wrapper.getLayer().getOrdinal())
        .max()
        .getAsInt() + 1;
  }

  private int getNextAvailableLayerGroupId() {
    return getLayerGroups().values().stream()
        .mapToInt(group -> group.getId())
        .max()
        .getAsInt() + 1;
  }

  private void deleteLayerWrapper(int layerId) {
    Set<OpenTCSDrawingView> drawingViews = getDrawingViews();
    drawingViews.forEach(drawingView -> drawingView.getDrawing().willChange());

    Set<ModelComponent> componentsToDelete = getComponents().get(layerId).stream()
        .map(component -> (ModelComponent) component)
        .collect(Collectors.toSet());
    drawingViews.forEach(drawingView -> drawingView.delete(componentsToDelete));

    drawingViews.forEach(drawingView -> drawingView.getDrawing().changed());

    getComponents().remove(layerId);

    // Remove the deleted layer wrapper from the system model's layout.
    removeLayerWrapper(layerId);
  }

  /**
   * Returns the set of drawing views the layer manager is working with.
   *
   * @return The set of drawing views the layer manager is working with.
   */
  private Set<OpenTCSDrawingView> getDrawingViews() {
    return getViewManager().getDrawingViewMap().values().stream()
        .map(scrollPane -> scrollPane.getDrawingView())
        .collect(Collectors.toSet());
  }

  private void handleActiveLayerRemoved() {
    List<Layer> layersByOrdinal = getLayerWrappers().values().stream()
        .map(wrapper -> wrapper.getLayer())
        .sorted(Comparator.comparing(layer -> layer.getOrdinal()))
        .collect(Collectors.toList());

    Optional<Layer> layerUnderRemovedActiveLayer = layersByOrdinal.stream()
        .takeWhile(layer -> layer.getOrdinal() < activeLayerWrapper.getLayer().getOrdinal())
        .reduce((layer1, layer2) -> layer2);

    // If there's a layer right under the active layer that just has been removed, select that layer
    // as the new active layer. Otherwise, just select the lowest layer.
    if (layerUnderRemovedActiveLayer.isPresent()) {
      setLayerActive(layerUnderRemovedActiveLayer.get().getId());
    }
    else {
      setLayerActive(layersByOrdinal.get(0).getId());
    }
  }

  private void shiftLayerByOne(int layerId, List<LayerWrapper> layers) {
    LayerWrapper layerWrapper = getLayerWrapper(layerId);
    int layerWrapperBeforeIndex = layers.indexOf(layerWrapper) - 1;
    LayerWrapper layerWrapperBefore = layers.get(layerWrapperBeforeIndex);
    swapLayerOrdinals(layerWrapper, layerWrapperBefore);
    updateLayerComponentsInDrawing(layerWrapper.getLayer(), layerWrapperBefore.getLayer());
  }

  private void swapLayerOrdinals(LayerWrapper layerWrapper1, LayerWrapper layerWrapper2) {
    int ordinal1 = layerWrapper1.getLayer().getOrdinal();
    int ordinal2 = layerWrapper2.getLayer().getOrdinal();

    Layer oldLayer = layerWrapper1.getLayer();
    Layer newLayer = oldLayer.withOrdinal(ordinal2);
    layerWrapper1.setLayer(newLayer);

    oldLayer = layerWrapper2.getLayer();
    newLayer = oldLayer.withOrdinal(ordinal1);
    layerWrapper2.setLayer(newLayer);
  }

  private void updateLayerComponentsInDrawing(Layer... layers) {
    Set<DrawnModelComponent> componentsToUpdate = new HashSet<>();
    for (Layer layer : layers) {
      if (layer.isVisible()) {
        componentsToUpdate.addAll(getComponents().get(layer.getId()));
      }
    }

    Set<Drawing> drawings = getDrawings();

    drawings.forEach(drawing -> drawing.willChange());
    for (DrawnModelComponent modelComponent : componentsToUpdate) {
      AbstractFigure figure = (AbstractFigure) getSystemModel().getFigure(modelComponent);
      drawings.forEach(drawing -> {
        drawing.basicRemove(figure);
        drawing.basicAdd(figure);
      });
    }
    drawings.forEach(drawing -> drawing.changed());
  }

  /**
   * Adds the given layer group to the system model's layout.
   *
   * @param layerWrapper The layer group to add.
   * @throws IllegalArgumentException If a layer group with the same layer group ID already exists
   * in the system model's layout.
   */
  private void addLayerGroup(LayerGroup layerGroup)
      throws IllegalArgumentException {
    int groupId = layerGroup.getId();
    checkArgument(getLayerGroup(groupId) == null,
                  "A layer group for group ID '%d' already exists in the model.",
                  groupId);

    getLayerGroups().put(groupId, layerGroup);
  }

  /**
   * Removes the layer group with the given group ID from the system model's layout.
   *
   * @param layerId The layer group ID.
   */
  private void removeLayerGroup(int groupId) {
    getLayerGroups().remove(groupId);
  }

  /**
   * Adds the given layer wrapper to the system model's layout.
   *
   * @param layerWrapper The layer wrapper to add.
   * @throws IllegalArgumentException If a layer wrapper with the same layer ID already exists
   * in the system model's layout.
   */
  private void addLayerWrapper(LayerWrapper layerWrapper)
      throws IllegalArgumentException {
    int layerId = layerWrapper.getLayer().getId();
    checkArgument(getLayerWrapper(layerId) == null,
                  "A layer wrapper for layer ID '%d' already exists in the model.",
                  layerId);

    getLayerWrappers().put(layerId, layerWrapper);
  }

  /**
   * Removes the layer wrapper with the given layer ID from the system model's layout.
   *
   * @param layerId The layer ID.
   */
  private void removeLayerWrapper(int layerId) {
    getLayerWrappers().remove(layerId);
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/SetPositionCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import javax.annotation.Nullable;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;

/**
 * A command to set a vehicle's position.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetPositionCommand
    implements AdapterCommand {

  /**
   * The position to set.
   */
  private final String position;

  /**
   * Creates a new instance.
   *
   * @param position The position to set.
   */
  public SetPositionCommand(@Nullable String position) {
    this.position = position;
  }

  @Override
  public void execute(VehicleCommAdapter adapter) {
    adapter.getProcessModel().setVehiclePosition(position);
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/persistence/ModelImportAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.persistence;

import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Provider;
import org.opentcs.access.to.model.BlockCreationTO;
import org.opentcs.access.to.model.LocationCreationTO;
import org.opentcs.access.to.model.LocationTypeCreationTO;
import org.opentcs.access.to.model.PathCreationTO;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.model.PointCreationTO;
import org.opentcs.access.to.model.VehicleCreationTO;
import org.opentcs.access.to.model.VisualLayoutCreationTO;
import org.opentcs.guing.application.StatusPanel;
import org.opentcs.guing.components.properties.type.KeyValueProperty;
import org.opentcs.guing.components.properties.type.Property;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.unified.PlantModelElementConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Converts plant model data to {@link SystemModel} instances.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelImportAdapter {

  /**
   * This class' logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ModelImportAdapter.class);

  private final Provider<SystemModel> systemModelProvider;
  /**
   * Converts single elements of a plant model.
   */
  private final PlantModelElementConverter elementConverter;
  /**
   * Validates model components and the system model.
   */
  private final ModelValidator validator;
  /**
   * The status panel of the plant overview.
   */
  private final StatusPanel statusPanel;

  @Inject
  public ModelImportAdapter(Provider<SystemModel> systemModelProvider,
                            PlantModelElementConverter elementConverter,
                            ModelValidator validator,
                            StatusPanel statusPanel) {
    this.systemModelProvider = requireNonNull(systemModelProvider, "systemModelProvider");
    this.elementConverter = requireNonNull(elementConverter, "elementConverter");
    this.validator = requireNonNull(validator, "validator");
    this.statusPanel = requireNonNull(statusPanel, "statusPanel");
  }

  /**
   * Converts the given plant model data to a {@link SystemModel} instance.
   *
   * @param model The plant model data to be converted.
   * @return The converted model.
   * @throws IllegalArgumentException If the given plant model data was inconsistent in some way.
   */
  @Nonnull
  public SystemModel convert(PlantModelCreationTO model)
      throws IllegalArgumentException {
    requireNonNull(model, "model");
//    checkArgument(!model.getVisualLayouts().isEmpty(), "Model does not contain a visual layout");

    SystemModel systemModel = systemModelProvider.get();
    systemModel.setName(model.getName());

    VisualLayoutCreationTO layoutTO = model.getVisualLayout();

    Set<String> collectedErrorMessages = new HashSet<>();

    importVisualLayout(layoutTO, systemModel, collectedErrorMessages);
    importPoints(model, systemModel, collectedErrorMessages);
    importPaths(model, systemModel, collectedErrorMessages);
    importVehicles(model, systemModel, collectedErrorMessages);
    importLocationTypes(model, systemModel, collectedErrorMessages);
    importLocations(model, systemModel, collectedErrorMessages);
    importBlocks(model, systemModel, collectedErrorMessages);

    importProperties(model, systemModel);

    // If any errors occurred, show the dialog with all errors listed
    if (!collectedErrorMessages.isEmpty()) {
      validator.showLoadingValidationWarning(statusPanel, collectedErrorMessages);
    }

    return systemModel;
  }

  private void importProperties(PlantModelCreationTO model, SystemModel systemModel) {
    for (Map.Entry<String, String> property : model.getProperties().entrySet()) {
      systemModel.getPropertyMiscellaneous().addItem(new KeyValueProperty(systemModel,
                                                                          property.getKey(),
                                                                          property.getValue()));
    }
  }

  private void importVisualLayout(VisualLayoutCreationTO layoutTO, SystemModel systemModel,
                                  Set<String> collectedErrorMessages) {
    LayoutModel layoutModel = elementConverter.importLayout(layoutTO);
    if (validModelComponent(layoutModel, systemModel, collectedErrorMessages)) {
      updateLayoutInModel(layoutModel, systemModel);
    }
  }

  private void importBlocks(PlantModelCreationTO model,
                            SystemModel systemModel,
                            Set<String> collectedErrorMessages) {
    for (BlockCreationTO blockTO : model.getBlocks()) {
      BlockModel blockModel = elementConverter.importBlock(blockTO);
      if (validModelComponent(blockModel, systemModel, collectedErrorMessages)) {
        addBlockToModel(blockModel, systemModel);
      }
    }
  }

  private void importLocations(PlantModelCreationTO model,
                               SystemModel systemModel,
                               Set<String> collectedErrorMessages) {
    for (LocationCreationTO locationTO : model.getLocations()) {
      LocationModel locationModel = elementConverter.importLocation(locationTO,
                                                                    model.getLocationTypes(),
                                                                    systemModel);
      if (validModelComponent(locationModel, systemModel, collectedErrorMessages)) {
        addLocationToModel(locationModel, systemModel);

        for (Map.Entry<String, Set<String>> entry : locationTO.getLinks().entrySet()) {
          LinkModel linkModel = elementConverter.importLocationLink(locationTO,
                                                                    entry.getKey(),
                                                                    entry.getValue(),
                                                                    systemModel);
          if (validModelComponent(linkModel, systemModel, collectedErrorMessages)) {
            addLinkToModel(linkModel, systemModel);
          }
        }
      }
    }
  }

  private void importLocationTypes(PlantModelCreationTO model,
                                   SystemModel systemModel,
                                   Set<String> collectedErrorMessages) {
    for (LocationTypeCreationTO locTypeTO : model.getLocationTypes()) {
      LocationTypeModel locTypeModel = elementConverter.importLocationType(locTypeTO);
      if (validModelComponent(locTypeModel, systemModel, collectedErrorMessages)) {
        addLocationTypeToModel(locTypeModel, systemModel);
      }
    }
  }

  private void importVehicles(PlantModelCreationTO model,
                              SystemModel systemModel,
                              Set<String> collectedErrorMessages) {
    for (VehicleCreationTO vehicleTO : model.getVehicles()) {
      VehicleModel vehicleModel = elementConverter.importVehicle(vehicleTO);
      if (validModelComponent(vehicleModel, systemModel, collectedErrorMessages)) {
        addVehicleToModel(vehicleModel, systemModel);
      }
    }
  }

  private void importPaths(PlantModelCreationTO model,
                           SystemModel systemModel,
                           Set<String> collectedErrorMessages) {
    for (PathCreationTO pathTO : model.getPaths()) {
      PathModel pathModel = elementConverter.importPath(pathTO, systemModel);
      if (validModelComponent(pathModel, systemModel, collectedErrorMessages)) {
        addPathToModel(pathModel, systemModel);
      }
    }
  }

  private void importPoints(PlantModelCreationTO model,
                            SystemModel systemModel,
                            Set<String> collectedErrorMessages) {
    for (PointCreationTO pointTO : model.getPoints()) {
      PointModel pointModel = elementConverter.importPoint(pointTO, systemModel);
      if (validModelComponent(pointModel, systemModel, collectedErrorMessages)) {
        addPointToModel(pointModel, systemModel);
      }
    }
  }

  private boolean validModelComponent(ModelComponent modelComponent,
                                      SystemModel systemModel,
                                      Set<String> collectedErrorMessages) {
    if (validator.isValidWith(systemModel, modelComponent)) {
      return true;
    }
    else {
      String deserializationError = validator.formatDeserializationErrors(modelComponent,
                                                                          validator.getErrors());
      validator.formatDeserializationErrors(modelComponent, validator.getErrors());
      validator.resetErrors();
      LOG.warn("Deserialization error: {}", deserializationError);
      collectedErrorMessages.add(deserializationError);
      return false;
    }
  }

  private void addPointToModel(PointModel point, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.POINTS).add(point);
  }

  private void addPathToModel(PathModel path, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.PATHS).add(path);
  }

  private void addVehicleToModel(VehicleModel vehicle, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.VEHICLES).add(vehicle);
  }

  private void addLocationTypeToModel(LocationTypeModel locType, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.LOCATION_TYPES).add(locType);
  }

  private void addLocationToModel(LocationModel location, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.LOCATIONS).add(location);
  }

  private void addLinkToModel(LinkModel link, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.LINKS).add(link);
  }

  private void addBlockToModel(BlockModel block, SystemModel systemModel) {
    systemModel.getMainFolder(SystemModel.FolderKey.BLOCKS).add(block);
  }

  private void updateLayoutInModel(LayoutModel layout, SystemModel systemModel) {
    // SystemModel already contains a LayoutModel, just copy the properties
    ModelComponent layoutComponent = systemModel.getMainFolder(SystemModel.FolderKey.LAYOUT);
    for (Map.Entry<String, Property> property : layout.getProperties().entrySet()) {
      layoutComponent.setProperty(property.getKey(), property.getValue());
    }
  }

}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/v003/PathTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence.v003;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(propOrder = {"name", "sourcePoint", "destinationPoint", "length", "maxVelocity",
                      "maxReverseVelocity", "locked", "properties"})
public class PathTO
    extends PlantModelElementTO {

  private String sourcePoint = "";
  private String destinationPoint = "";
  private Long length = 0L;
  private Long maxVelocity = 0L;
  private Long maxReverseVelocity = 0L;
  private Boolean locked = false;

  @XmlAttribute(required = true)
  public String getSourcePoint() {
    return sourcePoint;
  }

  public PathTO setSourcePoint(@Nonnull String sourcePoint) {
    requireNonNull(sourcePoint, "sourcePoint");
    this.sourcePoint = sourcePoint;
    return this;
  }

  @XmlAttribute(required = true)
  public String getDestinationPoint() {
    return destinationPoint;
  }

  public PathTO setDestinationPoint(@Nonnull String destinationPoint) {
    requireNonNull(destinationPoint, "destinationPoint");
    this.destinationPoint = destinationPoint;
    return this;
  }

  @XmlAttribute
  @XmlSchemaType(name = "unsignedInt")
  public Long getLength() {
    return length;
  }

  public PathTO setLength(@Nonnull Long length) {
    requireNonNull(length, "length");
    this.length = length;
    return this;
  }

  @XmlAttribute(required = true)
  @XmlSchemaType(name = "unsignedInt")
  public Long getMaxVelocity() {
    return maxVelocity;
  }

  public PathTO setMaxVelocity(@Nonnull Long maxVelocity) {
    requireNonNull(maxVelocity, "maxVelocity");
    this.maxVelocity = maxVelocity;
    return this;
  }

  @XmlAttribute(required = true)
  @XmlSchemaType(name = "unsignedInt")
  public Long getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  public PathTO setMaxReverseVelocity(@Nonnull Long maxReverseVelocity) {
    requireNonNull(maxReverseVelocity, "maxReverseVelocity");
    this.maxReverseVelocity = maxReverseVelocity;
    return this;
  }

  @XmlAttribute(required = true)
  public Boolean isLocked() {
    return locked;
  }

  public PathTO setLocked(Boolean locked) {
    this.locked = locked;
    return this;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/figures/ToolTipTextGenerator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opentcs.data.model.Vehicle;
import org.opentcs.guing.components.properties.type.KeyValueSetProperty;
import org.opentcs.guing.model.ModelComponent;
import static org.opentcs.guing.model.ModelComponent.MISCELLANEOUS;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.persistence.ModelManager;

/**
 * Generates tooltip texts for various model elements.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ToolTipTextGenerator {

  /**
   * The model manager.
   */
  private final ModelManager modelManager;

  @Inject
  public ToolTipTextGenerator(ModelManager modelManager) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
  }

  public String getToolTipText(PointModel model) {
    String pointDesc = model.getDescription();
    StringBuilder sb = new StringBuilder("<html>");
    sb.append(pointDesc).append(" ").append("<b>").append(model.getName()).append("</b>");

    appendBlockInfo(sb, model);
    appendMiscProps(sb, model);

    sb.append("</html>");

    return sb.toString();
  }

  public String getToolTipText(LocationModel model) {
    String locationDesc = model.getDescription();
    StringBuilder sb = new StringBuilder("<html>");
    sb.append(locationDesc).append(" ").append("<b>").append(model.getName()).append("</b>");

    appendBlockInfo(sb, model);
    appendPeripheralInformation(sb, model);
    appendMiscProps(sb, model);

    sb.append("</html>");

    return sb.toString();
  }

  public String getToolTipText(PathModel model) {
    String pathDesc = model.getDescription();
    StringBuilder sb = new StringBuilder("<html>");
    sb.append(pathDesc).append(" ").append("<b>").append(model.getName()).append("</b>");

    appendBlockInfo(sb, model);
    appendMiscProps(sb, model);

    sb.append("</html>");

    return sb.toString();
  }

  public String getToolTipText(VehicleModel model) {
    String vehicleDesc = model.getDescription();
    StringBuilder sb = new StringBuilder("<html>");

    sb.append(vehicleDesc).append(" ").append("<b>").append(model.getName()).append("</b>");

    appendVehicleState(sb, model);
    appendMiscProps(sb, model);

    sb.append("</html>");

    return sb.toString();
  }

  public String getToolTipText(LinkModel model) {
    return new StringBuilder("<html>")
        .append(model.getDescription()).append(" ")
        .append("<b>").append(model.getName()).append("</b>")
        .append("</html>").toString();
  }

  private String energyColorString(Vehicle vehicle) {
    if (vehicle.isEnergyLevelCritical()) {
      return "red";
    }
    else if (vehicle.isEnergyLevelDegraded()) {
      return "orange";
    }
    else if (vehicle.isEnergyLevelGood()) {
      return "green";
    }
    else {
      return "black";
    }
  }

  private String stateColorString(Vehicle vehicle) {
    switch (vehicle.getState()) {
      case ERROR:
        return "red";
      case UNAVAILABLE:
      case UNKNOWN:
        return "orange";
      default:
        return "black";
    }
  }

  private void appendBlockInfo(StringBuilder sb, ModelComponent component) {
    sb.append(blocksToToolTipContent(getBlocksWith(component)));
  }

  private void appendBlockInfo(StringBuilder sb, LocationModel location) {
    List<LinkModel> links = modelManager.getModel().getLinkModels();
    links = links.stream()
        .filter(link -> link.getLocation().getName().equals(location.getName()))
        .collect(Collectors.toList());

    List<BlockModel> partOfBlocks = new ArrayList<>();
    for (LinkModel link : links) {
      partOfBlocks.addAll(getBlocksWith(link.getPoint()));
    }

    sb.append(blocksToToolTipContent(partOfBlocks));
  }

  private void appendMiscProps(StringBuilder sb, ModelComponent component) {
    KeyValueSetProperty miscProps = (KeyValueSetProperty) component.getProperty(MISCELLANEOUS);

    if (miscProps.getItems().isEmpty()) {
      return;
    }

    sb.append("<hr>");
    sb.append(miscProps.getDescription()).append(": ");
    sb.append("<ul>");
    miscProps.getItems().stream()
        .sorted((o1, o2) -> o1.getKey().compareTo(o2.getKey()))
        .forEach(kvp -> {
          sb.append("<li>")
              .append(kvp.getKey()).append(": ").append(kvp.getValue())
              .append("</li>");
        });
    sb.append("</ul>");
  }

  private void appendVehicleState(StringBuilder sb, VehicleModel model) {
    sb.append("<hr>").append(model.getPropertyPoint().getDescription()).append(": ")
        .append(model.getPoint() != null ? model.getPoint().getName() : "?");
    sb.append("<br>").append(model.getPropertyNextPoint().getDescription()).append(": ")
        .append(model.getNextPoint() != null ? model.getNextPoint().getName() : "?");

    sb.append("<br>").append(model.getPropertyState().getDescription())
        .append(": <font color=").append(stateColorString(model.getVehicle())).append(">")
        .append(model.getPropertyState().getValue())
        .append("</font>");

    sb.append("<br>").append(model.getPropertyProcState().getDescription()).append(": ")
        .append(model.getPropertyProcState().getValue());
    sb.append("<br>").append(model.getPropertyIntegrationLevel().getDescription()).append(": ")
        .append(model.getPropertyIntegrationLevel().getValue());

    sb.append("<br>").append(model.getPropertyEnergyLevel().getDescription())
        .append(": <font color=").append(energyColorString(model.getVehicle())).append(">")
        .append(model.getPropertyEnergyLevel().getValue())
        .append("%</font>");
  }

  private void appendPeripheralInformation(StringBuilder sb, LocationModel model) {
    sb.append("<hr>");
    sb.append("<br>").append(model.getPropertyPeripheralReservationToken().getDescription())
        .append(": ")
        .append(model.getPropertyPeripheralReservationToken().getText());
    sb.append("<br>").append(model.getPropertyPeripheralState().getDescription())
        .append(": ")
        .append(model.getPropertyPeripheralState().getText());
    sb.append("<br>").append(model.getPropertyPeripheralProcState().getDescription())
        .append(": ")
        .append(model.getPropertyPeripheralProcState().getText());
    sb.append("<br>").append(model.getPropertyPeripheralJob().getDescription())
        .append(": ")
        .append(model.getPropertyPeripheralJob().getText());
  }

  private List<BlockModel> getBlocksWith(ModelComponent component) {
    List<BlockModel> result = new ArrayList<>();
    List<BlockModel> blocks = modelManager.getModel().getBlockModels();
    for (BlockModel block : blocks) {
      if (block.contains(component)) {
        result.add(block);
      }
    }
    return result;
  }

  private String blocksToToolTipContent(List<BlockModel> blocks) {
    if (blocks.isEmpty()) {
      return "";
    }

    blocks.sort((b1, b2) -> b1.getName().compareTo(b2.getName()));

    String desc = blocks.get(0).getDescription();
    StringBuilder sb = new StringBuilder("<hr>")
        .append(desc).append(": ");
    for (BlockModel block : blocks) {
      sb.append(block.getName()).append(", ");
    }
    sb.delete(sb.lastIndexOf(", "), sb.length());

    return sb.toString();
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/AcceptableInvalidValue.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

/**
 * An invalid but still acceptable value for a property.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface AcceptableInvalidValue {

  /**
   * Returns a description for the value.
   *
   * @return A description.
   */
  String getDescription();

  /**
   * Returns a helptext for the value.
   *
   * @return A helptext.
   */
  String getHelptext();
}


<|start_filename|>openTCS-ModelEditor/src/guiceConfig/java/org/opentcs/guing/RunModelEditor.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.util.Modules;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import org.opentcs.configuration.ConfigurationBindingProvider;
import org.opentcs.configuration.cfg4j.Cfg4jConfigurationBindingProvider;
import org.opentcs.customizations.ConfigurableInjectionModule;
import org.opentcs.customizations.plantoverview.PlantOverviewInjectionModule;
import org.opentcs.guing.application.PlantOverviewStarter;
import org.opentcs.util.Environment;
import org.opentcs.util.logging.UncaughtExceptionLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The plant overview process's default entry point.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RunModelEditor {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(RunModelEditor.class);

  /**
   * Prevents external instantiation.
   */
  private RunModelEditor() {
  }

  /**
   * The plant overview client's main entry point.
   *
   * @param args the command line arguments
   */
  public static void main(final String[] args) {
    System.setSecurityManager(new SecurityManager());
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(false));

    Environment.logSystemInfo();

    Injector injector = Guice.createInjector(customConfigurationModule());
    injector.getInstance(PlantOverviewStarter.class).startPlantOverview();
  }

  /**
   * Builds and returns a Guice module containing the custom configuration for the plant overview
   * application, including additions and overrides by the user.
   *
   * @return The custom configuration module.
   */
  private static Module customConfigurationModule() {
    ConfigurationBindingProvider bindingProvider = configurationBindingProvider();
    ConfigurableInjectionModule plantOverviewInjectionModule
        = new DefaultPlantOverviewInjectionModule();
    plantOverviewInjectionModule.setConfigBindingProvider(bindingProvider);
    return Modules.override(plantOverviewInjectionModule)
        .with(findRegisteredModules(bindingProvider));
  }

  /**
   * Finds and returns all Guice modules registered via ServiceLoader.
   *
   * @return The registered/found modules.
   */
  private static List<PlantOverviewInjectionModule> findRegisteredModules(
      ConfigurationBindingProvider bindingProvider) {
    List<PlantOverviewInjectionModule> registeredModules = new LinkedList<>();
    for (PlantOverviewInjectionModule module
             : ServiceLoader.load(PlantOverviewInjectionModule.class)) {
      LOG.info("Integrating injection module {}", module.getClass().getName());
      module.setConfigBindingProvider(bindingProvider);
      registeredModules.add(module);
    }
    return registeredModules;
  }

  private static ConfigurationBindingProvider configurationBindingProvider() {
    return new Cfg4jConfigurationBindingProvider(
        Paths.get(System.getProperty("opentcs.base", "."),
                  "config",
                  "opentcs-modeleditor-defaults-baseline.properties")
            .toAbsolutePath(),
        Paths.get(System.getProperty("opentcs.base", "."),
                  "config",
                  "opentcs-modeleditor-defaults-custom.properties")
            .toAbsolutePath(),
        Paths.get(System.getProperty("opentcs.home", "."),
                  "config",
                  "opentcs-modeleditor.properties")
            .toAbsolutePath()
    );
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/services/StandardSchedulerService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.services;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.access.SchedulerAllocationState;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.components.kernel.services.SchedulerService;
import org.opentcs.customizations.kernel.GlobalSyncObject;

/**
 * This class is the standard implementation of the {@link SchedulerService} interface.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class StandardSchedulerService
    implements SchedulerService {

  /**
   * A global object to be used for synchronization within the kernel.
   */
  private final Object globalSyncObject;
  /**
   * The scheduler.
   */
  private final Scheduler scheduler;

  /**
   * Creates a new instance.
   *
   * @param globalSyncObject The kernel threads' global synchronization object.
   * @param scheduler The scheduler.
   */
  @Inject
  public StandardSchedulerService(@GlobalSyncObject Object globalSyncObject,
                                  Scheduler scheduler) {
    this.globalSyncObject = requireNonNull(globalSyncObject, "globalSyncObject");
    this.scheduler = requireNonNull(scheduler, "scheduler");
  }

  @Override
  public SchedulerAllocationState fetchSchedulerAllocations() {
    synchronized (globalSyncObject) {
      return new SchedulerAllocationState(scheduler.getAllocations());
    }
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/commands/SetStateCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback.commands;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;

/**
 * A command to set the peripheral device's state.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SetStateCommand
    implements PeripheralAdapterCommand {

  /**
   * The peripheral device state to set.
   */
  private final PeripheralInformation.State state;

  /**
   * Creates a new instance.
   *
   * @param state The peripheral device state to set.
   */
  public SetStateCommand(@Nonnull PeripheralInformation.State state) {
    this.state = requireNonNull(state, "state");
  }

  @Override
  public void execute(PeripheralCommAdapter adapter) {
    if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
      return;
    }

    LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
    loopbackAdapter.updateState(state);
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/drivers/peripherals/PeripheralProcessModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.drivers.peripherals;

import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.PeripheralInformation;
import org.opentcs.data.model.TCSResourceReference;

/**
 * A model of a peripheral device's and its communication adapter's attributes.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralProcessModel
    implements Serializable {

  /**
   * The reference to the location that is attached to this model.
   */
  private final TCSResourceReference<Location> location;
  /**
   * Whether the communication adapter is currently enabled.
   */
  private final boolean commAdapterEnabled;
  /**
   * Whether the communication adapter is currently connected to the peripheral device.
   */
  private final boolean commAdapterConnected;
  /**
   * The peripheral device's current state.
   */
  private final PeripheralInformation.State state;

  /**
   * Creates a new instance.
   *
   * @param location The reference to the location that is attached to this model.
   */
  public PeripheralProcessModel(TCSResourceReference<Location> location) {
    this(location, false, false, PeripheralInformation.State.NO_PERIPHERAL);
  }

  protected PeripheralProcessModel(@Nonnull TCSResourceReference<Location> location,
                                   boolean commAdapterEnabled,
                                   boolean commAdapterConnected,
                                   @Nonnull PeripheralInformation.State state) {
    this.location = requireNonNull(location, "location");
    this.commAdapterEnabled = commAdapterEnabled;
    this.commAdapterConnected = commAdapterConnected;
    this.state = requireNonNull(state, "state");
  }

  /**
   * Returns the reference to the location that is attached to this model.
   *
   * @return The reference to the location that is attached to this model.
   */
  @Nonnull
  public TCSResourceReference<Location> getLocation() {
    return location;
  }

  /**
   * Creates a copy of the object, with the given location reference.
   *
   * @param location The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralProcessModel withLocation(
      @Nonnull TCSResourceReference<Location> location) {
    return new PeripheralProcessModel(location, commAdapterEnabled, commAdapterConnected, state);
  }

  /**
   * Returns whether the communication adapter is currently enabled.
   *
   * @return Whether the communication adapter is currently enabled.
   */
  public boolean isCommAdapterEnabled() {
    return commAdapterEnabled;
  }

  /**
   * Creates a copy of the object, with the given enabled state.
   *
   * @param commAdapterEnabled The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralProcessModel withCommAdapterEnabled(boolean commAdapterEnabled) {
    return new PeripheralProcessModel(location, commAdapterEnabled, commAdapterConnected, state);
  }

  /**
   * Returns whether the communication adapter is currently connected to the peripheral device.
   *
   * @return Whether the communication adapter is currently connected to the peripheral device.
   */
  public boolean isCommAdapterConnected() {
    return commAdapterConnected;
  }

  /**
   * Creates a copy of the object, with the given connected state.
   *
   * @param commAdapterConnected The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralProcessModel withCommAdapterConnected(boolean commAdapterConnected) {
    return new PeripheralProcessModel(location, commAdapterEnabled, commAdapterConnected, state);
  }

  /**
   * Returns the peripheral device's current state.
   *
   * @return The peripheral device's current state.
   */
  public PeripheralInformation.State getState() {
    return state;
  }

  /**
   * Creates a copy of the object, with the given state.
   *
   * @param state The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PeripheralProcessModel withState(PeripheralInformation.State state) {
    return new PeripheralProcessModel(location, commAdapterEnabled, commAdapterConnected, state);
  }

  /**
   * Used to describe what has changed in a process model.
   */
  public enum Attribute {
    /**
     * Indicates a change of the location property.
     */
    LOCATION,
    /**
     * Indicates a change of the comm adapter enabled property.
     */
    COMM_ADAPTER_ENABLED,
    /**
     * Indicates a change of the comm adapter connected property.
     */
    COMM_ADAPTER_CONNECTED,
    /**
     * Indicates a change of the state property.
     */
    STATE;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/BlockUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import org.opentcs.data.model.Block;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.BlockSelector;
import org.opentcs.guing.util.IconToolkit;

/**
 * A Block object in the tree view.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 * @see Block
 */
public class BlockUserObject
    extends AbstractUserObject
    implements ContextObject {

  private final UserObjectContext context;
  /**
   * A helper for selecting blocks/block elements.
   */
  private final BlockSelector blockSelector;

  /**
   * Creates a new instance.
   *
   * @param dataObject The corresponding model component
   * @param context The user object context
   * @param guiManager The gui manager.
   * @param modelManager The model manager
   * @param blockSelector A helper for selecting blocks/block elements.
   */
  @Inject
  public BlockUserObject(@Assisted BlockModel dataObject,
                         @Assisted UserObjectContext context,
                         GuiManager guiManager,
                         ModelManager modelManager,
                         BlockSelector blockSelector) {
    super(dataObject, guiManager, modelManager);
    this.context = requireNonNull(context, "context");
    this.blockSelector = requireNonNull(blockSelector, "blockSelector");
  }

  @Override
  public JPopupMenu getPopupMenu() {
    JPopupMenu menu = context.getPopupMenu(null);

    return menu;
  }

  @Override
  public BlockModel getModelComponent() {
    return (BlockModel) super.getModelComponent();
  }

  @Override
  public void doubleClicked() {
    blockSelector.blockSelected(getModelComponent());
  }

  @Override
  public ImageIcon getIcon() {
    return IconToolkit.instance().createImageIcon("tree/block.18x18.png");
  }

  @Override
  public UserObjectContext.ContextType getContextType() {
    return context.getType();
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/parking/AbstractParkingPositionSupplierTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import org.junit.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.services.InternalPlantModelService;
import org.opentcs.data.model.Path;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.model.Vehicle;

/**
 * Tests for {@link AbstractParkingPositionSupplier}.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class AbstractParkingPositionSupplierTest {

  private InternalPlantModelService plantModelService;
  private Router router;
  private AbstractParkingPositionSupplierImpl supplier;

  public AbstractParkingPositionSupplierTest() {
  }

  @Before
  public void setUp() {
    plantModelService = mock(InternalPlantModelService.class);
    router = mock(Router.class);
    supplier = new AbstractParkingPositionSupplierImpl(plantModelService, router);

  }

  @Test
  public void returnsEmptyAllParkingPositionsOccupied() {
    Point point1 = new Point("vehicle's current position");
    Point point2 = new Point("parking position occupied by another vehicle")
        .withType(Point.Type.PARK_POSITION)
        .withOccupyingVehicle(new Vehicle("another vehicle").getReference());
    Point point3 = new Point("parking position occupied by yet another vehicle")
        .withType(Point.Type.PARK_POSITION)
        .withOccupyingVehicle(new Vehicle("yet another vehicle").getReference());
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));
    when(plantModelService.expandResources(Collections.singleton(point2.getReference())))
        .thenReturn(Collections.singleton(point2));
    when(plantModelService.expandResources(Collections.singleton(point3.getReference())))
        .thenReturn(Collections.singleton(point3));

    Set<Point> result = supplier.findUsableParkingPositions(vehicle);
    assertTrue(result.isEmpty());
  }

  @Test
  public void returnsUnoccupiedParkingPositions() {
    Point point1 = new Point("vehicle's current position");
    Point point2 = new Point("unoccupied parking position")
        .withType(Point.Type.PARK_POSITION);
    Point point3 = new Point("another unoccupied parking position")
        .withType(Point.Type.PARK_POSITION);
    Vehicle vehicle = new Vehicle("vehicle")
        .withCurrentPosition(point1.getReference());

    when(router.getTargetedPoints()).thenReturn(new HashSet<>());
    when(plantModelService.fetchObjects(eq(Point.class), any())).thenReturn(setOf(point2, point3));
    when(plantModelService.expandResources(Collections.singleton(point2.getReference())))
        .thenReturn(Collections.singleton(point2));
    when(plantModelService.expandResources(Collections.singleton(point3.getReference())))
        .thenReturn(Collections.singleton(point3));

    Set<Point> result = supplier.findUsableParkingPositions(vehicle);
    assertFalse(result.isEmpty());
    assertEquals(setOf(point2, point3), result);
  }

  @Test
  public void returnsExpandedPoints() {
    Point[] points = new Point[5];
    Path[] paths = new Path[points.length];
    for (int i = 0; i < points.length; i++) {
      points[i] = new Point("Point" + i);
      paths[i] = new Path("Path" + i,
                          new Point("some point").getReference(),
                          new Point("some other point").getReference());
    }

    Set<TCSResource<?>> blockMembers = setOf(points[1], points[2], points[3],
                                             paths[0], paths[4]);

    when(plantModelService.fetchObjects(Point.class)).thenReturn(setOf(points));
    when(plantModelService.expandResources(Collections.singleton(points[2].getReference())))
        .thenReturn(blockMembers);

    Set<Point> result = supplier.expandPoints(points[2]);
    assertFalse(result.isEmpty());
    assertEquals(setOf(points[1], points[2], points[3]), result);
  }

  @SuppressWarnings("unchecked")
  private <T> Set<T> setOf(T... resources) {
    return new HashSet<>(Arrays.asList(resources));
  }

  public class AbstractParkingPositionSupplierImpl
      extends AbstractParkingPositionSupplier {

    public AbstractParkingPositionSupplierImpl(InternalPlantModelService plantModelService,
                                               Router router) {
      super(plantModelService, router);
    }

    @Override
    public Optional<Point> findParkingPosition(Vehicle vehicle) {
      throw new UnsupportedOperationException("Outside of this test's scope.");
    }
  }
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/EventBuffer.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import static org.opentcs.util.Assertions.checkArgument;
import org.opentcs.util.event.EventHandler;

/**
 * Stores events and keeps them until a client fetches them.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EventBuffer
    implements EventHandler {

  /**
   * The buffered events.
   */
  private final List<Object> events = new LinkedList<>();
  /**
   * This buffer's event filter.
   */
  private Predicate<Object> eventFilter;
  /**
   * A flag indicating whether this event buffer's client is currently waiting for an event.
   */
  private boolean waitingClient;

  /**
   * Creates a new instance
   *
   * @param eventFilter This buffer's initial event filter.
   */
  public EventBuffer(@Nonnull Predicate<Object> eventFilter) {
    this.eventFilter = requireNonNull(eventFilter, "eventFilter");
  }

  // Methods declared in interface EventListener start here
  @Override
  public void onEvent(Object event) {
    requireNonNull(event, "event");
    synchronized (events) {
      if (eventFilter.test(event)) {
        events.add(event);
        // If the client is waiting for an event, wake it up, since there is one
        // now.
        if (waitingClient) {
          events.notify();
        }
      }
    }
  }

  // Methods not declared in any interface start here
  /**
   * Returns a list of events that are currently stored in this buffer and
   * clears the buffer.
   * If the buffer is currently empty, block until an event arrives, or for the
   * specified amount of time to pass, whichever occurs first.
   *
   * @param timeout The maximum amount of time (in ms) to wait for an event to
   * arrive. Must be at least 0 (in which case this method will return
   * immediately, without waiting for an event to arrive).
   * @return A list of events that are currently stored in this buffer.
   * @throws IllegalArgumentException If <code>timeout</code> is less than 0.
   */
  public List<Object> getEvents(long timeout)
      throws IllegalArgumentException {
    checkArgument(timeout >= 0, "timeout < 0: %s", timeout);
    synchronized (events) {
      if (timeout > 0 && events.isEmpty()) {
        waitingClient = true;
        try {
          events.wait(timeout);
        }
        catch (InterruptedException exc) {
          throw new IllegalStateException("Unexpectedly interrupted", exc);
        }
        finally {
          waitingClient = false;
        }
      }
      List<Object> result = new LinkedList<>(events);
      events.clear();
      return result;
    }
  }

  /**
   * Checks whether a client is currently waiting for events arriving in this
   * buffer.
   *
   * @return <code>true</code> if a client is currently waiting, else
   * <code>false</code>.
   */
  public boolean hasWaitingClient() {
    synchronized (events) {
      return waitingClient;
    }
  }

  /**
   * Sets this buffer's event filter.
   *
   * @param eventFilter This buffer's new event filter.
   */
  public void setEventFilter(@Nonnull Predicate<Object> eventFilter) {
    synchronized (events) {
      this.eventFilter = requireNonNull(eventFilter);
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/PointTypeProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.List;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.PointModel.Type;

/**
 * Subclass for a {@link Type} selection property.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PointTypeProperty
    extends SelectionProperty<Type> {

  public PointTypeProperty(ModelComponent model) {
    super(model);
  }

  public PointTypeProperty(ModelComponent model,
                           List<Type> possibleValues,
                           Object value) {
    super(model, possibleValues, value);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/tree/elements/LocationTypeUserObject.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.tree.elements;

import com.google.inject.assistedinject.Assisted;
import javax.inject.Inject;
import javax.swing.ImageIcon;
import org.opentcs.guing.application.GuiManager;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.IconToolkit;

/**
 * Represents a location type in the TreeView.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class LocationTypeUserObject
    extends AbstractUserObject {

  /**
   * Creates a new instance of StationUserObject
   *
   * @param modelComponent
   * @param guiManager The gui manager.
   * @param modelManager The model manager
   */
  @Inject
  public LocationTypeUserObject(@Assisted LocationTypeModel modelComponent,
                                GuiManager guiManager,
                                ModelManager modelManager) {
    super(modelComponent, guiManager, modelManager);
  }

  @Override
  public LocationTypeModel getModelComponent() {
    return (LocationTypeModel) super.getModelComponent();
  }

  @Override
  public ImageIcon getIcon() {
    return IconToolkit.instance().createImageIcon("tree/locationType.18x18.png");
  }

  @Override
  public void doubleClicked() {
    getGuiManager().figureSelected(getModelComponent());
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/phase/assignment/priorization/VehicleComparatorIdleFirstTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.assignment.priorization;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.theInstance;
import org.junit.*;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorIdleFirst;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleComparatorIdleFirstTest {

  private VehicleComparatorIdleFirst comparator;

  @Before
  public void setUp() {
    comparator = new VehicleComparatorIdleFirst();
  }

  @Test
  public void sortIdleVehiclesUp() {
    Vehicle vehicle1 = new Vehicle("Vehicle1").withState(Vehicle.State.CHARGING);
    Vehicle vehicle2 = vehicle1.withState(Vehicle.State.IDLE);
    Vehicle vehicle3 = vehicle1.withState(Vehicle.State.CHARGING);

    List<Vehicle> list = new ArrayList<>();
    list.add(vehicle1);
    list.add(vehicle2);
    list.add(vehicle3);

    Collections.sort(list, comparator);

    assertThat(list.get(0), is(theInstance(vehicle2)));
  }

}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/util/I18nPlantOverviewModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

/**
 * Defines application-specific constants regarding internationalization.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface I18nPlantOverviewModeling {
  
  /**
   * Path to the resources related to the create group dialog.
   */
  String CREATEGROUP_PATH = "i18n.org.opentcs.plantoverview.modeling.dialogs.createGroup";
  /**
   * Path to the resources related to dockables.
   */
  String DOCKABLE_PATH = "i18n.org.opentcs.plantoverview.modeling.panels.dockable";
  /**
   * Path to the resources related to layers.
   */
  String LAYERS_PATH = "i18n.org.opentcs.plantoverview.modeling.panels.layers";
  /**
   * Path to the resources related the menu bar.
   */
  String MENU_PATH = "i18n.org.opentcs.plantoverview.modeling.mainMenu";
  /**
   * Path to miscellaneous resources
   */
  String MISC_PATH = "i18n.org.opentcs.plantoverview.modeling.miscellaneous";
  /**
   * Path to the resources related to status messages.
   */
  String STATUS_PATH = "i18n.org.opentcs.plantoverview.modeling.panels.status";
  /**
   * Path to the resources related to the system.
   */
  String SYSTEM_PATH = "i18n.org.opentcs.plantoverview.modeling.system";
  /**
   * Path to the resources related to toolbars.
   */
  String TOOLBAR_PATH = "i18n.org.opentcs.plantoverview.modeling.toolbar";
  /**
   * Path to the resources related to model validator.
   */
  String VALIDATOR_PATH = "i18n.org.opentcs.plantoverview.modeling.modelValidation";
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/services/RemoteTCSObjectServiceProxy.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.services;

import java.rmi.RemoteException;
import java.util.Set;
import java.util.function.Predicate;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.ObjectHistory;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;

/**
 * The default implementation of the tcs object service.
 * Delegates method invocations to the corresponding remote service.
 *
 * @author <NAME> (Fraunhofer IML)
 * @param <R> The remote service's type.
 */
abstract class RemoteTCSObjectServiceProxy<R extends RemoteTCSObjectService>
    extends AbstractRemoteServiceProxy<R>
    implements TCSObjectService {

  @Override
  public <T extends TCSObject<T>> T fetchObject(Class<T> clazz, TCSObjectReference<T> ref)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchObject(getClientId(), clazz, ref);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public <T extends TCSObject<T>> T fetchObject(Class<T> clazz, String name)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchObject(getClientId(), clazz, name);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public <T extends TCSObject<T>> Set<T> fetchObjects(Class<T> clazz)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchObjects(getClientId(), clazz);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public <T extends TCSObject<T>> Set<T> fetchObjects(Class<T> clazz,
                                                      Predicate<? super T> predicate)
      throws KernelRuntimeException {
    checkServiceAvailability();

    try {
      return getRemoteService().fetchObjects(getClientId(), clazz, predicate);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void updateObjectProperty(TCSObjectReference<?> ref, String key, String value)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().updateObjectProperty(getClientId(), ref, key, value);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

  @Override
  public void appendObjectHistoryEntry(TCSObjectReference<?> ref, ObjectHistory.Entry entry)
      throws ObjectUnknownException, KernelRuntimeException {
    checkServiceAvailability();

    try {
      getRemoteService().appendObjectHistoryEntry(getClientId(), ref, entry);
    }
    catch (RemoteException ex) {
      throw findSuitableExceptionFor(ex);
    }
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/OpenTCSView.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application;

import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CVetoClosingEvent;
import bibliothek.gui.dock.common.event.CVetoClosingListener;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.logging.Level;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.border.EtchedBorder;
import org.jhotdraw.app.AbstractView;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.gui.URIChooser;
import org.jhotdraw.util.ReversedList;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.SharedKernelServicePortal;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.components.kernel.services.ServiceUnavailableException;
import org.opentcs.components.plantoverview.PlantModelExporter;
import org.opentcs.components.plantoverview.PlantModelImporter;
import org.opentcs.components.plantoverview.PluggablePanel;
import org.opentcs.components.plantoverview.PluggablePanelFactory;
import org.opentcs.customizations.ApplicationEventBus;
import org.opentcs.customizations.plantoverview.ApplicationFrame;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.notification.UserNotification;
import org.opentcs.guing.application.action.ToolBarManager;
import org.opentcs.guing.application.action.ViewActionMap;
import org.opentcs.guing.components.dialogs.VehiclesPanel;
import org.opentcs.guing.components.dockable.DockableHandlerFactory;
import org.opentcs.guing.components.dockable.DockingManagerOperating;
import org.opentcs.guing.components.dockable.DrawingViewFocusHandler;
import org.opentcs.guing.components.drawing.DrawingViewFactory;
import org.opentcs.guing.components.drawing.DrawingViewScrollPane;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditorOperating;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.drawing.course.OriginChangeListener;
import org.opentcs.guing.components.drawing.figures.FigureConstants;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.drawing.figures.LabeledPointFigure;
import org.opentcs.guing.components.layer.LayerManager;
import org.opentcs.guing.components.properties.SelectionPropertiesComponent;
import org.opentcs.guing.components.properties.event.AttributesChangeEvent;
import org.opentcs.guing.components.properties.event.AttributesChangeListener;
import org.opentcs.guing.components.properties.panel.PropertiesPanelFactory;
import org.opentcs.guing.components.properties.type.AbstractProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.components.tree.BlocksTreeViewManager;
import org.opentcs.guing.components.tree.ComponentsTreeViewManager;
import org.opentcs.guing.components.tree.TreeViewManager;
import org.opentcs.guing.components.tree.elements.UserObject;
import org.opentcs.guing.components.tree.elements.VehicleUserObject;
import org.opentcs.guing.event.BlockChangeEvent;
import org.opentcs.guing.event.BlockChangeListener;
import org.opentcs.guing.event.DrawingEditorEvent;
import org.opentcs.guing.event.DrawingEditorListener;
import org.opentcs.guing.event.KernelStateChangeEvent;
import org.opentcs.guing.event.ModelNameChangeEvent;
import org.opentcs.guing.event.OperationModeChangeEvent;
import org.opentcs.guing.event.ResetInteractionToolCommand;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.guing.exchange.TransportOrderUtil;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.PropertiesCollection;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.LinkModel;
import org.opentcs.guing.model.elements.LocationModel;
import org.opentcs.guing.model.elements.LocationTypeModel;
import org.opentcs.guing.model.elements.PathModel;
import org.opentcs.guing.model.elements.PointModel;
import org.opentcs.guing.model.elements.VehicleModel;
import org.opentcs.guing.peripherals.jobs.PeripheralJobsContainerPanel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.transport.orders.TransportOrdersContainerPanel;
import org.opentcs.guing.transport.sequences.OrderSequencesContainerPanel;
import org.opentcs.guing.util.Cursors;
import org.opentcs.guing.util.I18nPlantOverviewOperating;
import org.opentcs.guing.util.PanelRegistry;
import org.opentcs.guing.util.PlantOverviewOperatingApplicationConfiguration;
import org.opentcs.guing.util.UserMessageHelper;
import org.opentcs.thirdparty.jhotdraw.application.action.edit.UndoRedoManager;
import org.opentcs.thirdparty.jhotdraw.application.action.file.CloseFileAction;
import org.opentcs.thirdparty.jhotdraw.application.toolbar.PaletteToolBarBorder;
import org.opentcs.thirdparty.jhotdraw.components.drawing.AbstractOpenTCSDrawingView;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.event.EventBus;
import org.opentcs.util.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Visualizes the driving course and other kernel objects as well as messages
 * received by the kernel.
 * (Contains everything underneath the tool bars.)
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class OpenTCSView
    extends AbstractView
    implements GuiManager,
               ComponentsManager,
               PluginPanelManager,
               EventHandler {

  /**
   * The name/title of this application.
   */
  public static final String NAME
      = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.MISC_PATH).getString("openTcsView.applicationName.text");
  /**
   * Property key for the currently loaded driving course model.
   * The corresponding value contains a "*" if the model has been modified.
   */
  public static final String MODELNAME_PROPERTY = "modelName";
  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(OpenTCSView.class);
  /**
   * This instance's resource bundle.
   */
  private final ResourceBundleUtil bundle
      = ResourceBundleUtil.getBundle(I18nPlantOverviewOperating.MISC_PATH);
  /**
   * Provides/manages the application's current state.
   */
  private final ApplicationState appState;
  /**
   * Allows for undoing and redoing actions.
   */
  private final UndoRedoManager fUndoRedoManager;
  /**
   * The drawing editor.
   */
  private final OpenTCSDrawingEditorOperating fDrawingEditor;
  /**
   * The JFrame.
   */
  private final JFrame fFrame;
  /**
   * Utility to manage the views.
   */
  private final ViewManagerOperating viewManager;
  /**
   * A manager for the components tree view.
   */
  private final TreeViewManager fComponentsTreeManager;
  /**
   * A manager for the blocks tree view.
   */
  private final TreeViewManager fBlocksTreeManager;
  /**
   * Displays properties of the currently selected model component(s).
   */
  private final SelectionPropertiesComponent fPropertiesComponent;
  /**
   * Manages driving course models.
   */
  private final ModelManager fModelManager;
  /**
   * Indicates the progress for lengthy operations.
   */
  private final ProgressIndicator progressIndicator;
  /**
   * Manages docking frames.
   */
  private final DockingManagerOperating dockingManager;
  /**
   * Registry for plugin panels.
   */
  private final PanelRegistry panelRegistry;
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * The shared portal to be used.
   */
  private SharedKernelServicePortal sharedPortal;
  /**
   * A panel that displays kernel messages.
   */
  private final KernelStatusPanel kernelStatusPanel;
  /**
   * A panel for mouse position/status.
   */
  private final StatusPanel statusPanel;
  /**
   * A panel showing all vehicles in the system model.
   */
  private final VehiclesPanel vehiclesPanel;
  /**
   * Shows messages to the user.
   */
  private final UserMessageHelper userMessageHelper;
  /**
   * A factory for drawing views.
   */
  private final DrawingViewFactory drawingViewFactory;
  /**
   * Handles block events.
   */
  private final BlockChangeListener blockEventHandler = new BlockEventHandler();
  /**
   * Handles events for changes of properties.
   */
  private final AttributesChangeListener attributesEventHandler = new AttributesEventHandler();
  /**
   * A provider for ActionMaps.
   */
  private final Provider<ViewActionMap> actionMapProvider;
  /**
   * A provider for the tool bar manager.
   */
  private final Provider<ToolBarManager> toolBarManagerProvider;
  /**
   * A factory for properties-related panels.
   */
  private final PropertiesPanelFactory propertiesPanelFactory;
  /**
   * A provider for panels showing the transport orders.
   */
  private final Provider<TransportOrdersContainerPanel> toContainerPanelProvider;
  /**
   * A provider for panels showing the order sequences.
   */
  private final Provider<OrderSequencesContainerPanel> osContainerPanelProvider;
  /**
   * A provider for panels showing the peripheral jobs.
   */
  private final Provider<PeripheralJobsContainerPanel> pjContainerPanelProvider;
  /**
   * A helper for creating transport orders with the kernel.
   */
  private final TransportOrderUtil orderUtil;
  /**
   * The application's event bus.
   */
  private final EventBus eventBus;
  /**
   * Handles focussing of dockables.
   */
  private final DrawingViewFocusHandler drawingViewFocusHandler;
  /**
   * A factory for handlers related to dockables.
   */
  private final DockableHandlerFactory dockableHandlerFactory;
  /**
   * The layer manager.
   */
  private final LayerManager layerManager;
  /**
   * The operations desk application's configuration.
   */
  private final PlantOverviewOperatingApplicationConfiguration configuration;
  /**
   * Provides the application's tool bars.
   */
  private ToolBarManager toolBarManager;

  /**
   * Creates a new instance.
   *
   * @param appState Provides/manages the application's current state.
   * @param appFrame The <code>JFrame</code> this view is wrapped in.
   * @param progressIndicator The progress indicator to be used.
   * @param portalProvider Provides a access to a portal.
   * @param viewManager The view manager to be used.
   * @param tcsDrawingEditor The drawing editor to be used.
   * @param modelManager The model manager to be used.
   * @param statusPanel The status panel to be used.
   * @param panelRegistry The plugin panel registry to be used.
   * @param userMessageHelper An UserMessageHelper
   * @param drawingViewFactory A factory for drawing views.
   * @param undoRedoManager Allows for undoing and redoing actions.
   * @param componentsTreeManager Manages the components tree view.
   * @param blocksTreeManager Manages the blocks tree view.
   * @param kernelStatusPanel A panel that displays kernel messages.
   * @param propertiesComponent Displays properties of the currently selected model component(s).
   * @param vehiclesPanel A panel showing all the vehicles in the system model.
   * @param actionMapProvider A provider for ActionMaps.
   * @param toolBarManagerProvider A provider for the tool bar manager.
   * @param propertiesPanelFactory A factory for properties-related panels.
   * @param toContainerPanelProvider A provider for panels showing the transport orders.
   * @param osContainerPanelProvider A provider for panels showing the order sequences.
   * @param pjContainerPanelProvider A provider for panels showing the peripheral jobs.
   * @param orderUtil A helper for creating transport orders with the kernel.
   * @param eventBus The application's event bus.
   * @param dockingManager Manages docking frames.
   * @param drawingViewFocusHandler Handles focussing of dockables.
   * @param dockableHandlerFactory A factory for handlers related to dockables.
   * @param layerManager The layer manager.
   * @param configuration The operations desk application's configuration.
   */
  @Inject
  public OpenTCSView(ApplicationState appState,
                     @ApplicationFrame JFrame appFrame,
                     ProgressIndicator progressIndicator,
                     SharedKernelServicePortalProvider portalProvider,
                     ViewManagerOperating viewManager,
                     OpenTCSDrawingEditorOperating tcsDrawingEditor,
                     ModelManager modelManager,
                     StatusPanel statusPanel,
                     PanelRegistry panelRegistry,
                     UserMessageHelper userMessageHelper,
                     DrawingViewFactory drawingViewFactory,
                     UndoRedoManager undoRedoManager,
                     ComponentsTreeViewManager componentsTreeManager,
                     BlocksTreeViewManager blocksTreeManager,
                     KernelStatusPanel kernelStatusPanel,
                     SelectionPropertiesComponent propertiesComponent,
                     VehiclesPanel vehiclesPanel,
                     Provider<ViewActionMap> actionMapProvider,
                     Provider<ToolBarManager> toolBarManagerProvider,
                     PropertiesPanelFactory propertiesPanelFactory,
                     Provider<TransportOrdersContainerPanel> toContainerPanelProvider,
                     Provider<OrderSequencesContainerPanel> osContainerPanelProvider,
                     Provider<PeripheralJobsContainerPanel> pjContainerPanelProvider,
                     TransportOrderUtil orderUtil,
                     @ApplicationEventBus EventBus eventBus,
                     DockingManagerOperating dockingManager,
                     DrawingViewFocusHandler drawingViewFocusHandler,
                     DockableHandlerFactory dockableHandlerFactory,
                     LayerManager layerManager,
                     PlantOverviewOperatingApplicationConfiguration configuration) {
    this.appState = requireNonNull(appState, "appState");
    this.fFrame = requireNonNull(appFrame, "appFrame");
    this.progressIndicator = requireNonNull(progressIndicator, "progressIndicator");
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.viewManager = requireNonNull(viewManager, "viewManager");
    this.fDrawingEditor = requireNonNull(tcsDrawingEditor, "tcsDrawingEditor");
    this.fModelManager = requireNonNull(modelManager, "modelManager");
    this.statusPanel = requireNonNull(statusPanel, "statusPanel");
    this.panelRegistry = requireNonNull(panelRegistry, "panelRegistry");
    this.userMessageHelper = requireNonNull(userMessageHelper, "userMessageHelper");
    this.drawingViewFactory = requireNonNull(drawingViewFactory, "drawingViewFactory");
    this.fUndoRedoManager = requireNonNull(undoRedoManager, "undoRedoManager");
    this.fComponentsTreeManager = requireNonNull(componentsTreeManager, "componentsTreeManager");
    this.fBlocksTreeManager = requireNonNull(blocksTreeManager, "blocksTreeManager");
    this.kernelStatusPanel = requireNonNull(kernelStatusPanel, "kernelStatusPanel");
    this.fPropertiesComponent = requireNonNull(propertiesComponent, "propertiesComponent");
    this.vehiclesPanel = requireNonNull(vehiclesPanel, "vehiclesPanel");
    this.actionMapProvider = requireNonNull(actionMapProvider, "actionMapProvider");
    this.toolBarManagerProvider = requireNonNull(toolBarManagerProvider, "toolBarManagerProvider");
    this.propertiesPanelFactory = requireNonNull(propertiesPanelFactory, "propertiesPanelFactory");
    this.toContainerPanelProvider = requireNonNull(toContainerPanelProvider,
                                                   "toContainerPanelProvider");
    this.osContainerPanelProvider = requireNonNull(osContainerPanelProvider,
                                                   "osContainerPanelProvider");
    this.pjContainerPanelProvider = requireNonNull(pjContainerPanelProvider,
                                                   "pjContainerPanelProvider");
    this.orderUtil = requireNonNull(orderUtil, "orderUtil");
    this.eventBus = requireNonNull(eventBus, "eventBus");
    this.dockingManager = requireNonNull(dockingManager, "dockingManager");
    this.drawingViewFocusHandler = requireNonNull(drawingViewFocusHandler,
                                                  "drawingViewFocusHandler");
    this.dockableHandlerFactory = requireNonNull(dockableHandlerFactory, "dockableHandlerFactory");
    this.layerManager = requireNonNull(layerManager, "layerManager");
    this.configuration = requireNonNull(configuration, "configuration");
  }

  @Override // AbstractView
  public void init() {
    eventBus.subscribe(this);

    progressIndicator.setProgress(StartupProgressStatus.INITIALIZED);

    fDrawingEditor.addDrawingEditorListener(new DrawingEditorEventHandler(fModelManager));

    eventBus.subscribe(fComponentsTreeManager);

    progressIndicator.setProgress(StartupProgressStatus.INITIALIZE_MODEL);
    setSystemModel(fModelManager.getModel());

    // Properties view (lower left corner)
    fPropertiesComponent.setPropertiesContent(
        propertiesPanelFactory.createPropertiesTableContent(this));

    // Register a listener for dragging vehicles around.
    VehicleDragHandler listener = new VehicleDragHandler(Cursors.getDragVehicleCursor());
    fComponentsTreeManager.addMouseListener(listener);
    fComponentsTreeManager.addMouseMotionListener(listener);

    setActionMap(actionMapProvider.get());
    this.toolBarManager = toolBarManagerProvider.get();
    eventBus.subscribe(toolBarManager);

    eventBus.subscribe(fPropertiesComponent);
    eventBus.subscribe(vehiclesPanel);
    eventBus.subscribe(fUndoRedoManager);
    eventBus.subscribe(fDrawingEditor);

    layerManager.initialize();

    initializeFrame();
    viewManager.init();
    createEmptyModel();

    switchToOperatingState();
  }

  @Override // AbstractView
  public void stop() {
    LOG.info("GUI terminating...");
    eventBus.unsubscribe(this);
    System.exit(0);
  }

  @Override  // AbstractView
  public void clear() {
  }

  @Override
  public void onEvent(Object event) {
    if (event instanceof SystemModelTransitionEvent) {
      handleSystemModelTransition((SystemModelTransitionEvent) event);
    }
    if (event instanceof KernelStateChangeEvent) {
      handleKernelStateChangeEvent((KernelStateChangeEvent) event);
    }
  }

  private void handleSystemModelTransition(SystemModelTransitionEvent evt) {
    switch (evt.getStage()) {
      case LOADED:
        setHasUnsavedChanges(false);
        // Update model name in title
        setModelNameProperty(fModelManager.getModel().getName());
        break;
      default:
      // Do nada.
    }
  }

  @Override
  public void showPluginPanel(PluggablePanelFactory factory, boolean visible) {
    String id = factory.getClass().getName();
    SingleCDockable dockable = dockingManager.getCControl().getSingleDockable(id);
    if (dockable != null) {
      // dockable is not null at this point when the user hides the plugin 
      // panel by clicking on its menu entry
      PluggablePanel panel = (PluggablePanel) dockable.getFocusComponent();
      panel.terminate();
      if (!dockingManager.getCControl().removeDockable(dockable)) {
        LOG.warn("Couldn't remove dockable for plugin panel factory '{}'", factory);
        return;
      }
    }
    if (!visible) {
      return;
    }
    if (factory.providesPanel(OperationMode.equivalent(appState.getOperationMode()))) {
      PluggablePanel panel = factory.createPanel(OperationMode.equivalent(appState.getOperationMode()));
      DefaultSingleCDockable factoryDockable = dockingManager.createFloatingDockable(
          factory.getClass().getName(),
          factory.getPanelDescription(),
          panel);
      factoryDockable.addVetoClosingListener(new CVetoClosingListener() {

        @Override
        public void closing(CVetoClosingEvent event) {
        }

        @Override
        public void closed(CVetoClosingEvent event) {
          panel.terminate();
          dockingManager.getCControl().removeDockable(factoryDockable);
        }
      });
      panel.initialize();
    }
  }

  /**
   * Adds a new drawing view to the tabbed wrappingPanel.
   *
   * @return The newly created Dockable.
   */
  public DefaultSingleCDockable addDrawingView() {
    DrawingViewScrollPane newScrollPane
        = drawingViewFactory.createDrawingView(fModelManager.getModel(),
                                               toolBarManager.getSelectionToolButton(),
                                               toolBarManager.getDragToolButton());

    int drawingViewIndex = viewManager.getNextDrawingViewIndex();

    String title = bundle.getString("openTcsView.panel_operatingDrawingView.title") + " " + drawingViewIndex;
    DefaultSingleCDockable newDockable
        = dockingManager.createDockable("drivingCourse" + drawingViewIndex,
                                        title,
                                        newScrollPane,
                                        true);
    viewManager.addDrawingView(newDockable, newScrollPane);

    int lastIndex = Math.max(0, drawingViewIndex - 1);
    dockingManager.addTabTo(newDockable, DockingManagerOperating.COURSE_TAB_PANE_ID, lastIndex);

    newDockable.addVetoClosingListener(new DrawingViewClosingListener(newDockable));
    newDockable.addFocusListener(drawingViewFocusHandler);

    newScrollPane.getDrawingView().getComponent().dispatchEvent(new FocusEvent(this, FocusEvent.FOCUS_GAINED));
    firePropertyChange(AbstractOpenTCSDrawingView.FOCUS_GAINED, null, newDockable);

    return newDockable;
  }

  /**
   * Adds a new transport order view.
   */
  public void addTransportOrderView() {
    int biggestIndex = viewManager.getNextTransportOrderViewIndex();
    DefaultSingleCDockable lastTOView = viewManager.getLastTransportOrderView();
    TransportOrdersContainerPanel panel = toContainerPanelProvider.get();
    DefaultSingleCDockable newDockable
        = dockingManager.createDockable("transportOrders" + biggestIndex,
                                        bundle.getString(
                                            "openTcsView.panel_operatingTransportOrdersView.title")
                                        + " " + biggestIndex, panel, true);
    viewManager.addTransportOrderView(newDockable, panel);

    panel.initView();

    newDockable.addVetoClosingListener(
        dockableHandlerFactory.createDockableClosingHandler(newDockable));

    final int indexToInsert;

    if (lastTOView != null) {
      indexToInsert = dockingManager
          .getTabPane(DockingManagerOperating.COURSE_TAB_PANE_ID)
          .getStation()
          .indexOf(lastTOView.intern()) + 1;
    }
    else {
      indexToInsert = viewManager.getDrawingViewMap().size();
    }

    dockingManager.addTabTo(newDockable, DockingManagerOperating.COURSE_TAB_PANE_ID, indexToInsert);
  }

  /**
   * Adds a new order sequence view.
   */
  public void addTransportOrderSequenceView() {
    int biggestIndex = viewManager.getNextOrderSequenceViewIndex();
    DefaultSingleCDockable lastOSView = viewManager.getLastOrderSequenceView();

    OrderSequencesContainerPanel panel = osContainerPanelProvider.get();
    DefaultSingleCDockable newDockable
        = dockingManager.createDockable("orderSequences" + biggestIndex,
                                        bundle.getString(
                                            "openTcsView.panel_operatingOrderSequencesView.title")
                                        + " " + biggestIndex,
                                        panel, true);
    viewManager.addOrderSequenceView(newDockable, panel);

    panel.initView();

    newDockable.addVetoClosingListener(
        dockableHandlerFactory.createDockableClosingHandler(newDockable));

    final int indexToInsert;
    if (lastOSView != null) {
      indexToInsert = dockingManager
          .getTabPane(DockingManagerOperating.COURSE_TAB_PANE_ID)
          .getStation()
          .indexOf(lastOSView.intern()) + 1;
    }
    else {
      indexToInsert = viewManager.getTransportOrderMap().size()
          + viewManager.getDrawingViewMap().size();
    }
    dockingManager.addTabTo(newDockable, DockingManagerOperating.COURSE_TAB_PANE_ID, indexToInsert);
  }

  /**
   * Adds a new peripheral jobs view.
   */
  public void addPeripheralJobsView() {
    int biggestIndex = viewManager.getNextPeripheralJobViewIndex();
    DefaultSingleCDockable lastView = viewManager.getLastPeripheralJobView();

    PeripheralJobsContainerPanel panel = pjContainerPanelProvider.get();
    DefaultSingleCDockable newDockable
        = dockingManager.createDockable("peripheralJobs" + biggestIndex,
                                        bundle.getString(
                                            "openTcsView.panel_peripheralJobsView.title")
                                        + " " + biggestIndex,
                                        panel, true);
    viewManager.addPeripheralJobView(newDockable, panel);

    panel.initView();

    newDockable.addVetoClosingListener(
        dockableHandlerFactory.createDockableClosingHandler(newDockable));

    final int indexToInsert;
    if (lastView != null) {
      indexToInsert = dockingManager
          .getTabPane(DockingManagerOperating.COURSE_TAB_PANE_ID)
          .getStation()
          .indexOf(lastView.intern()) + 1;
    }
    else {
      indexToInsert = viewManager.getTransportOrderMap().size()
          + viewManager.getOrderSequenceMap().size()
          + viewManager.getDrawingViewMap().size();
    }
    dockingManager.addTabTo(newDockable, DockingManagerOperating.COURSE_TAB_PANE_ID, indexToInsert);
  }

  /**
   * Restores the layout to default.
   */
  public void resetWindowArrangement() {
    for (DefaultSingleCDockable dock : new ArrayList<>(viewManager.getDrawingViewMap().keySet())) {
      removeDrawingView(dock);
    }
    for (DefaultSingleCDockable dock : new ArrayList<>(viewManager.getTransportOrderMap().keySet())) {
      dockingManager.removeDockable(dock);
    }
    for (DefaultSingleCDockable dock : new ArrayList<>(viewManager.getOrderSequenceMap().keySet())) {
      dockingManager.removeDockable(dock);
    }
    dockingManager.reset();
    closeOpenedPluginPanels();
    viewManager.reset();

    initializeFrame();
    viewManager.init();

    // Depending on the current kernel state there may exist panels, now, that shouldn't be visible.
    new Thread(() -> setOperatingState()).start();
  }

  /**
   * Logs a message to the status text area.
   *
   * @param message The message to log.
   */
  private void log(UserNotification message) {
    kernelStatusPanel.display(message);
  }

  @Override  // GuiManager
  public void createEmptyModel() {
    CloseFileAction action = (CloseFileAction) getActionMap().get(CloseFileAction.ID);
    if (action != null) {
      action.actionPerformed(new ActionEvent(this,
                                             ActionEvent.ACTION_PERFORMED,
                                             CloseFileAction.ID_MODEL_CLOSING));
      if (action.getFileSavedStatus() == JOptionPane.CANCEL_OPTION) {
        return;
      }
    }

    // Clean up first...
    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.UNLOADING,
                                                    fModelManager.getModel()));

    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.UNLOADED,
                                                    fModelManager.getModel()));

    // Create the new, empty model.
    LOG.debug("Creating new driving course model...");
    fModelManager.createEmptyModel();

    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.LOADING,
                                                    fModelManager.getModel()));

    // Now let components set themselves up for the new model.
    setSystemModel(fModelManager.getModel());

    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.LOADED,
                                                    fModelManager.getModel()));

    // makes sure the origin is on the lower left side and the ruler
    // are correctly drawn
    fDrawingEditor.initializeViewport();
  }

  public void loadCurrentKernelModel() {
    try (SharedKernelServicePortal sharedPortal = portalProvider.register()) {
      loadCurrentKernelModel(sharedPortal.getPortal());
    }
    catch (ServiceUnavailableException exc) {
      LOG.info("Kernel unavailable, aborting.", exc);
    }
  }

  /**
   * Loads the current kernel model.
   */
  private void loadCurrentKernelModel(KernelServicePortal portal) {
    if (hasUnsavedChanges()) {
      if (!showUnsavedChangesDialog()) {
        return;
      }
    }
    if (portal.getState() == Kernel.State.MODELLING) {
      handleKernelInModellingMode();
      return;
    }
    restoreModel(portal);
  }

  /**
   * Initializes the model stored in the kernel or in the model manager.
   *
   * @param portal If not null, the model from the given kernel will be loaded, else the model from
   * the model manager
   */
  private void restoreModel(@Nullable KernelServicePortal portal) {
    progressIndicator.initialize();

    progressIndicator.setProgress(ModelRestorationProgressStatus.CLEANUP);
    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.UNLOADING,
                                                    fModelManager.getModel()));

    progressIndicator.setProgress(ModelRestorationProgressStatus.START_LOADING_MODEL);
    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.UNLOADED,
                                                    fModelManager.getModel()));

    if (portal == null) {
      fModelManager.restoreModel();
    }
    else {
      fModelManager.restoreModel(portal);
      statusPanel.setLogMessage(Level.INFO,
                                bundle.getFormatted("openTcsView.message_modelLoaded.text",
                                                    fModelManager.getModel().getName()));
    }

    progressIndicator.setProgress(ModelRestorationProgressStatus.SET_UP_MODEL_VIEW);
    eventBus.onEvent(new SystemModelTransitionEvent(this,
                                                    SystemModelTransitionEvent.Stage.LOADING,
                                                    fModelManager.getModel()));

    setSystemModel(fModelManager.getModel());

    progressIndicator.setProgress(ModelRestorationProgressStatus.SET_UP_DIRECTORY_TREE);

    progressIndicator.setProgress(ModelRestorationProgressStatus.SET_UP_WORKING_AREA);

    ModelComponent layoutComponent
        = fModelManager.getModel().getMainFolder(SystemModel.FolderKey.LAYOUT);
    layoutComponent.addAttributesChangeListener(attributesEventHandler);

    eventBus.onEvent(new SystemModelTransitionEvent(this, SystemModelTransitionEvent.Stage.LOADED,
                                                    fModelManager.getModel()));
    updateModelName();

    progressIndicator.terminate();
  }

  /**
   * Shows a dialog telling the user the plant overview state can't be switched
   * as long as it has unsaved changes.
   *
   * @return <code>true</code> if the user saved the model or
   * discarded the changes (the program can
   * continue normally), <code>false</code> if the user pressed cancel.
   */
  private boolean showSwitchStateUnsavedChangesDialog() {
    String title = bundle.getString("openTcsView.dialog_unsavedChanges.title");
    String text = bundle.getString("openTcsView.dialog_unsavedChanges.message");
    String[] options = {bundle.getString("openTcsView.dialog_unsavedChanges.option_upload.text"),
                        bundle.getString("openTcsView.dialog_unsavedChanges.option_discard.text"),
                        bundle.getString("openTcsView.dialog_unsavedChanges.option_cancel.text")};
    switch (userMessageHelper.showOptionsDialog(title,
                                                text,
                                                UserMessageHelper.Type.ERROR,
                                                options)) {
      case 0:
        return uploadModelToKernel();
      case 1:
        setHasUnsavedChanges(false);
        return true;
      default:
        return false;
    }
  }

  private void handleKernelStateChangeEvent(KernelStateChangeEvent event) {
    closeOpenedPluginPanels();
    switch (event.getNewState()) {
      case MODELLING:
        handleKernelInModellingMode();
        break;
      case OPERATING:
        if (hasUnsavedChanges()) {
          if (!showSwitchStateUnsavedChangesDialog()) {
            return;
          }
        }
        SwingUtilities.invokeLater(() -> loadCurrentKernelModel());
        break;
      case DISCONNECTED:
      case SHUTDOWN:
      default:
        handleNoKernelConnection();
    }
  }

  private void handleNoKernelConnection() {
    if (sharedPortal != null) {
      sharedPortal.close();
      sharedPortal = null;
    }
    JOptionPane.showMessageDialog(
        fFrame,
        bundle.getFormatted("openTcsView.optionPane_kernelConnectionLost.message"),
        bundle.getFormatted("openTcsView.optionPane_kernelConnectionLost.title"),
        JOptionPane.ERROR_MESSAGE
    );
    // XXX We should actually initiate a reconnect attempt here.
    System.exit(1);
  }

  /**
   * Switches the plant overview state.
   */
  private void switchToOperatingState() {
    try {
      sharedPortal = portalProvider.register();
      if (sharedPortal.getPortal().getState() != Kernel.State.OPERATING) {
        handleKernelInModellingMode();
      }
      setOperatingState();
      SwingUtilities.invokeLater(() -> loadCurrentKernelModel());
    }
    catch (ServiceUnavailableException exc) {
      handleNoKernelConnection();
    }
  }

  private void handleKernelInModellingMode() {
    createEmptyModel();
    String text = bundle.getFormatted("openTcsView.message_kernelInModelling.text",
                                      bundle.getString("openTcsView.state_modelling.text"),
                                      bundle.getString("openTcsView.state_operating.text"));
    log(new UserNotification(text, UserNotification.Level.INFORMATIONAL));
  }

  private void setModelNameProperty(String modelName) {
    fModelManager.getModel().setName(modelName);
    eventBus.onEvent(new ModelNameChangeEvent(this, modelName));
  }

  public void updateModelName() {
    String newName = fModelManager.getModel().getName();
    eventBus.onEvent(new ModelNameChangeEvent(this, newName));
  }

  /**
   * Adds a background image to the currently active drawing view.
   *
   * @param file The file with the image.
   */
  public void addBackgroundBitmap(File file) {
    getActiveDrawingView().addBackgroundBitmap(file);
  }

  @Override
  public List<UserObject> restoreModelComponents(List<UserObject> userObjects) {
    // This method is specific to modeling mode
    return new ArrayList<>();
  }

  @Override  // View
  public void write(URI f, URIChooser chooser)
      throws IOException {
  }

  @Override  // View
  public void read(URI f, URIChooser chooser)
      throws IOException {
  }

  @Override  // AbstractView
  public boolean canSaveTo(URI file) {
    return new File(file).getName().endsWith(".xml");
  }

  @Override  // AbstractView
  public URI getURI() {
    String modelName = fModelManager.getModel().getName();

    try {
      uri = new URI(modelName);
    }
    catch (URISyntaxException ex) {
      LOG.warn("URISyntaxException in getURI({})", modelName, ex);
    }

    return uri;
  }

  /**
   * Returns all drawing views (including the modelling view)
   *
   * @return List with all known <code>OpenTCSDrawingViews</code>.
   */
  private List<OpenTCSDrawingView> getDrawingViews() {
    List<OpenTCSDrawingView> views = new ArrayList<>();

    for (DrawingViewScrollPane scrollPane : viewManager.getDrawingViewMap().values()) {
      views.add(scrollPane.getDrawingView());
    }

    return views;
  }

  @Override
  public void selectModelComponent(ModelComponent modelComponent) {
    fPropertiesComponent.setModel(modelComponent);
    DrawingView drawingView = fDrawingEditor.getActiveView();
    drawingView.clearSelection();
    Figure figure = findFigure(modelComponent);
    // LocationType hat keine Figur
    if (figure != null) {
      drawingView.toggleSelection(figure);
    }
  }

  @Override// GuiManager
  public void addSelectedModelComponent(ModelComponent modelComponent) {
    Set<ModelComponent> components = fComponentsTreeManager.getSelectedItems();

    if (components.size() > 1) {
      components.add(modelComponent);

      DrawingView drawingView = fDrawingEditor.getActiveView();
      drawingView.clearSelection();

      Collection<Figure> figures = new LinkedList<>();
      for (ModelComponent comp : components) {
        Figure figure = findFigure(comp);

        // At least LocationTypes do not have a Figure!
        if (figure != null) {
          figures.add(figure);
        }
      }
      drawingView.addToSelection(figures);

      fPropertiesComponent.setModel(new PropertiesCollection(components));
      // Re-select all originally selected objects in the tree.
      fComponentsTreeManager.selectItems(components);
    }
    else {
      // In operating mode, only one component can be selected.
      selectModelComponent(modelComponent);
    }
  }

  @Override// GuiManager
  public boolean treeComponentRemoved(ModelComponent model) {
    return false;
  }

  @Override  // GuiManager
  public void figureSelected(ModelComponent modelComponent) {
    modelComponent.addAttributesChangeListener(attributesEventHandler);
    fPropertiesComponent.setModel(modelComponent);

    Figure figure = findFigure(modelComponent);
    OpenTCSDrawingView drawingView = fDrawingEditor.getActiveView();

    if (figure != null) {
      drawingView.clearSelection();
      drawingView.addToSelection(figure);
      // Scroll view to this figure.
      drawingView.scrollTo(figure);
    }
  }

  @Override  // GuiManager
  public void loadModel() {
  }

  @Override
  public void importModel(PlantModelImporter importer) {
  }

  /**
   * Shows a dialog to save unsaved changes.
   *
   * @return <code>true</code> if the user pressed yes or no, <code>false</code>
   * if the user pressed cancel.
   */
  private boolean showUnsavedChangesDialog() {
    CloseFileAction action = (CloseFileAction) getActionMap().get(CloseFileAction.ID);
    action.actionPerformed(new ActionEvent(this,
                                           ActionEvent.ACTION_PERFORMED,
                                           CloseFileAction.ID_MODEL_CLOSING));
    switch (action.getFileSavedStatus()) {
      case JOptionPane.YES_OPTION:
        super.setHasUnsavedChanges(false);
        return true;
      case JOptionPane.NO_OPTION:
        return true;
      case JOptionPane.CANCEL_OPTION:
        return false;
      default:
        return false;
    }
  }

  /**
   * Uploads the current (local) model to the kernel.
   *
   * @return Whether the model was actually uploaded.
   */
  private boolean uploadModelToKernel() {
    return false;
  }

  @Override
  public boolean saveModel() {
    boolean saved = fModelManager.saveModelToFile(false);
    if (saved) {
      String modelName = fModelManager.getModel().getName();
      setModelNameProperty(modelName);
      setHasUnsavedChanges(false);
    }
    return saved;
  }

  @Override  // GuiManager
  public boolean saveModelAs() {
    boolean saved = fModelManager.saveModelToFile(true);
    if (saved) {
      String modelName = fModelManager.getModel().getName();
      setModelNameProperty(modelName);
      setHasUnsavedChanges(false);
    }
    return saved;
  }

  @Override
  public void exportModel(PlantModelExporter exporter) {
  }

  @Override  // GuiManager
  public ModelComponent createModelComponent(Class<? extends ModelComponent> clazz) {
    // This method is specific to modeling mode
    return null;
  }

  private OpenTCSDrawingView getActiveDrawingView() {
    return fDrawingEditor.getActiveView();
  }

  private void removeDrawingView(DefaultSingleCDockable dock) {
    if (!viewManager.getDrawingViewMap().containsKey(dock)) {
      return;
    }

    fDrawingEditor.remove(viewManager.getDrawingViewMap().get(dock).getDrawingView());
    viewManager.removeDockable(dock);
    dockingManager.removeDockable(dock);
  }

  /**
   * Combines the OpenTCSView panel and the panel for the tool bars to a new
   * panel.
   *
   * @return The resulting panel.
   */
  private JPanel wrapViewComponent() {
    // Add a dummy toolbar for dragging.
    // (Preview to see how the tool bar would look like after dragging?)
    final JToolBar toolBar = new JToolBar();
    // A wholeComponentPanel for toolbars above the OpenTCSView wholeComponentPanel.
    final JPanel toolBarPanel = new JPanel();
    toolBarPanel.setLayout(new BoxLayout(toolBarPanel, BoxLayout.LINE_AXIS));
    toolBar.setBorder(new PaletteToolBarBorder());

    final List<JToolBar> lToolBars = new LinkedList<>();

    // The new wholeComponentPanel for the whole component.
    JPanel wholeComponentPanel = new JPanel(new BorderLayout());
    wholeComponentPanel.add(toolBarPanel, BorderLayout.NORTH);
    wholeComponentPanel.add(getComponent());
    lToolBars.add(toolBar);

    JPanel viewComponent = wholeComponentPanel;

    // XXX Why is this list iterated in *reverse* order?
    for (JToolBar curToolBar : new ReversedList<>(toolBarManager.getToolBars())) {
      // A panel that wraps the toolbar.
      final JPanel curToolBarPanel = new JPanel();
      curToolBarPanel.setLayout(new BoxLayout(curToolBarPanel, BoxLayout.LINE_AXIS));
      // A panel that wraps the (wrapped) toolbar and the previous component
      // (the whole view and the nested/wrapped toolbars).
      JPanel wrappingPanel = new JPanel(new BorderLayout());
      curToolBar.setBorder(new PaletteToolBarBorder());

      curToolBarPanel.add(curToolBar);
      wrappingPanel.add(curToolBarPanel, BorderLayout.NORTH);
      wrappingPanel.add(viewComponent);

      lToolBars.add(curToolBar);
      viewComponent = wrappingPanel;
    }

    for (JToolBar bar : lToolBars) {
      configureToolBarButtons(bar);
    }

    return viewComponent;
  }

  private void configureToolBarButtons(JToolBar bar) {
    final Dimension dimButton = new Dimension(32, 34);
    for (Component comp : bar.getComponents()) {
      if (comp instanceof JButton || comp instanceof JToggleButton) {
        JComponent tbButton = (JComponent) comp;
        tbButton.setMaximumSize(dimButton);
        tbButton.setPreferredSize(dimButton);
        tbButton.setBorder(new EtchedBorder());
      }
    }
  }

  private void closeOpenedPluginPanels() {
    for (PluggablePanelFactory factory : panelRegistry.getFactories()) {
      showPluginPanel(factory, false);
    }
  }

  /**
   * Initializes operating state.
   */
  private void setOperatingState() {
    appState.setOperationMode(OperationMode.OPERATING);
    Runnable run = new Runnable() {

      @Override
      public void run() {
        // XXX The event should probably be emitted in ApplicationState now.
        eventBus.onEvent(new OperationModeChangeEvent(this,
                                                      OperationMode.UNDEFINED,
                                                      OperationMode.OPERATING));
      }
    };

    if (SwingUtilities.isEventDispatchThread()) {
      // Called from File -> Mode
      SwingUtilities.invokeLater(run);
    }
    else {
      try {
        // Called from Main.connectKernel()
        SwingUtilities.invokeAndWait(run);
      }
      catch (InterruptedException | InvocationTargetException ex) {
        LOG.error("Unexpected exception ", ex);
      }
    }

    // Switch to selection tool.
    eventBus.onEvent(new ResetInteractionToolCommand(this));
  }

  /**
   * Removes the given model component from the given folder.
   *
   * @param folder The folder.
   * @param model The component to be removed.
   */
  private boolean removeModelComponent(ModelComponent folder,
                                       ModelComponent model) {
    if (!folder.contains(model)) {
      return false;
    }

    // This method is being called by command objects that use undo/redo, so
    // avoid calling commands via undo/redo here.
    boolean componentRemoved = false;

    synchronized (model) {
      if (!BlockModel.class.isInstance(folder)) {
        // don't delete objects from a Blocks folder
        synchronized (folder) {
          folder.remove(model);
        }

        model.removeAttributesChangeListener(attributesEventHandler);
        componentRemoved = true;
      }

      fPropertiesComponent.reset();

      if (model instanceof BlockModel) {
        BlockModel blockModel = (BlockModel) model;
        // Remove Blocks from the Blocks tree
        fBlocksTreeManager.removeItem(blockModel);
        blockModel.blockRemoved();
        blockModel.removeBlockChangeListener(blockEventHandler);
      }
      else if (componentRemoved) {
        fComponentsTreeManager.removeItem(model);
      }

      if (model instanceof LocationTypeModel) {
        for (LocationModel location : fModelManager.getModel().getLocationModels()) {
          location.updateTypeProperty(fModelManager.getModel().getLocationTypeModels());
        }
      }

      setHasUnsavedChanges(true);
    }

    return componentRemoved;
  }

  /**
   * Returns the figure that belongs to the given model component.
   *
   * @param model The model component.
   * @return The figure that belongs to the given model component, or
   * <code>null</code>, if there isn't any.
   */
  private Figure findFigure(ModelComponent model) {
    return fModelManager.getModel().getFigure(model);
  }

  private void setSystemModel(SystemModel systemModel) {
    requireNonNull(systemModel, "systemModel");

    long timeBefore = System.currentTimeMillis();

    // Notify the view's scroll panes about the new systemModel and therefore about the new/changed
    // origin. This way they can handle changes made to the origin's scale.
    for (DrawingViewScrollPane scrollPane : viewManager.getDrawingViewMap().values()) {
      scrollPane.originChanged(systemModel.getDrawingMethod().getOrigin());
    }

    fDrawingEditor.setSystemModel(systemModel);

    // --- Undo, Redo, Clipboard ---
    Drawing drawing = fDrawingEditor.getDrawing();
    drawing.addUndoableEditListener(fUndoRedoManager);

    fComponentsTreeManager.restoreTreeView(systemModel);
    fComponentsTreeManager.sortItems();
    fComponentsTreeManager.getTreeView().getTree().scrollRowToVisible(0);
    fBlocksTreeManager.restoreTreeView(systemModel.getMainFolder(SystemModel.FolderKey.BLOCKS));
    fBlocksTreeManager.getTreeView().sortRoot();
    fBlocksTreeManager.getTreeView().getTree().scrollRowToVisible(0);

    // Add Attribute Change Listeners to all objects
    for (VehicleModel vehicle : systemModel.getVehicleModels()) {
      vehicle.addAttributesChangeListener(attributesEventHandler);
    }

    systemModel.getLayoutModel().addAttributesChangeListener(attributesEventHandler);

    for (PointModel point : systemModel.getPointModels()) {
      point.addAttributesChangeListener(attributesEventHandler);
    }

    for (PathModel path : systemModel.getPathModels()) {
      path.addAttributesChangeListener(attributesEventHandler);
    }

    for (LocationTypeModel locationType : systemModel.getLocationTypeModels()) {
      locationType.addAttributesChangeListener(attributesEventHandler);
    }

    for (LocationModel location : systemModel.getLocationModels()) {
      location.addAttributesChangeListener(attributesEventHandler);
    }

    for (LinkModel link : systemModel.getLinkModels()) {
      link.addAttributesChangeListener(attributesEventHandler);
    }

    for (BlockModel block : systemModel.getBlockModels()) {
      block.addAttributesChangeListener(attributesEventHandler);
      block.addBlockChangeListener(blockEventHandler);
    }

    LOG.debug("setSystemModel() took {} ms.", System.currentTimeMillis() - timeBefore);
  }

  /**
   * Initializes the frame with the toolbars and the dockable elements.
   */
  private void initializeFrame() {
    if (!SwingUtilities.isEventDispatchThread()) {
      try {
        SwingUtilities.invokeAndWait(() -> initializeFrame());
      }
      catch (InterruptedException | InvocationTargetException e) {
        LOG.warn("Exception initializing frame", e);
      }
      return;
    }

    fFrame.getContentPane().removeAll();
    dockingManager.initializeDockables();
    // Frame
    fFrame.setLayout(new BorderLayout());
    fFrame.add(wrapViewComponent(), BorderLayout.NORTH);
    fFrame.add(dockingManager.getCControl().getContentArea());
    fFrame.add(statusPanel, BorderLayout.SOUTH);
    restoreDockables();
    // Ensure that, after initialization, the selection tool is active.
    // This needs to be done after the initial drawing views have been set
    // up so they reflect the behaviour of the selected tool.
    // XXX Maybe there is a better way to ensure this...
    toolBarManager.getDragToolButton().doClick();
    toolBarManager.getSelectionToolButton().doClick();
  }

  private void restoreDockables() {
    addDrawingView();

    addTransportOrderView();
    addTransportOrderSequenceView();
    if (configuration.enablePeripheralJobsPanel()) {
      addPeripheralJobsView();
    }

    dockingManager.getTabPane(DockingManagerOperating.COURSE_TAB_PANE_ID)
        .getStation()
        .setFrontDockable(viewManager.evaluateFrontDockable());
  }

  private class AttributesEventHandler
      implements AttributesChangeListener {

    /**
     * Creates a new instance.
     */
    public AttributesEventHandler() {
    }

    @Override  // AttributesChangeListener
    public void propertiesChanged(AttributesChangeEvent event) {
      if (event.getInitiator() == this) {
        return;
      }

      ModelComponent model = event.getModel();

      // If a model component's name changed, update the blocks this component is a member of
      if (model.getPropertyName() != null && model.getPropertyName().hasChanged()) {
        fComponentsTreeManager.itemChanged(model);

        fModelManager.getModel().getBlockModels().stream()
            .filter(block -> blockAffectedByNameChange(block, model))
            .forEach(block -> updateBlockMembers(block));
      }

      if (model instanceof LayoutModel) {
        // Handle scale changes.
        LengthProperty pScaleX = (LengthProperty) model.getProperty(LayoutModel.SCALE_X);
        LengthProperty pScaleY = (LengthProperty) model.getProperty(LayoutModel.SCALE_Y);

        if (pScaleX.hasChanged() || pScaleY.hasChanged()) {
          double scaleX = (double) pScaleX.getValue();
          double scaleY = (double) pScaleY.getValue();

          if (scaleX != 0.0 && scaleY != 0.0) {
            fModelManager.getModel().getDrawingMethod().getOrigin().setScale(scaleX, scaleY);
          }
        }
      }

      if (model instanceof LocationModel) {
        if (model.getProperty(LocationModel.TYPE).hasChanged()) {
          AbstractProperty p = (AbstractProperty) model.getProperty(LocationModel.TYPE);
          LocationTypeModel type
              = fModelManager.getModel().getLocationTypeModel((String) p.getValue());
          ((LocationModel) model).setLocationType(type);
          if (model != event.getInitiator()) {
            model.propertiesChanged(this);
          }
        }
      }

      if (model instanceof LocationTypeModel) {
        for (LocationModel locModel : fModelManager.getModel().getLocationModels()) {
          locModel.updateTypeProperty(fModelManager.getModel().getLocationTypeModels());
        }
      }
    }

    private boolean blockAffectedByNameChange(BlockModel block, ModelComponent model) {
      return block.getChildComponents().stream().anyMatch(member -> member.equals(model));
    }

    private void updateBlockMembers(BlockModel block) {
      List<String> members = new ArrayList<>();
      for (ModelComponent component : block.getChildComponents()) {
        members.add(component.getName());
      }
      block.getPropertyElements().setItems(members);
    }
  }

  /**
   * Handles events emitted for changes of blocks.
   */
  private class BlockEventHandler
      implements BlockChangeListener {

    /**
     * Creates a new instance.
     */
    public BlockEventHandler() {
    }

    @Override  // BlockChangeListener
    public void courseElementsChanged(BlockChangeEvent event) {
      BlockModel block = (BlockModel) event.getSource();
      // Remove all children from the block and re-add those that are still there.
      fBlocksTreeManager.removeChildren(block);
      for (ModelComponent component : block.getChildComponents()) {
        fBlocksTreeManager.addItem(block, component);
      }

      setHasUnsavedChanges(true);
    }

    @Override
    public void colorChanged(BlockChangeEvent event) {
    }

    @Override  // BlockChangeListener
    public void blockRemoved(BlockChangeEvent event) {
    }
  }

  /**
   * Handles events emitted by the drawing editor.
   */
  private class DrawingEditorEventHandler
      implements DrawingEditorListener {

    /**
     * Provides access to the current system model.
     */
    private final ModelManager modelManager;

    /**
     * Creates a new instance.
     *
     * @param modelManager Provides access to the current system model.
     */
    public DrawingEditorEventHandler(ModelManager modelManager) {
      this.modelManager = requireNonNull(modelManager, "modelManager");
    }

    @Override  // DrawingEditorListener
    public void figureAdded(DrawingEditorEvent event) {
      Figure figure = event.getFigure();
      ModelComponent model = figure.get(FigureConstants.MODEL);

      // Some figures do not have a model - OriginFigure, for instance.
      // XXX Check if we can't unify all figures to have a model.
      if (model == null) {
        return;
      }

      if (figure instanceof AttributesChangeListener) {
        model.addAttributesChangeListener((AttributesChangeListener) figure);
      }

      // The added figure shall react on changes of the layout's scale.
      if (figure instanceof OriginChangeListener) {
        Origin ref = modelManager.getModel().getDrawingMethod().getOrigin();

        if (ref != null) {
          ref.addListener((OriginChangeListener) figure);
          figure.set(FigureConstants.ORIGIN, ref);
        }
      }

      fModelManager.getModel().registerFigure(model, figure);

//      ModelComponent folder = modelManager.getModel().getFolder(model);
//      addModelComponent(folder, model);
      if (figure instanceof LabeledFigure) {
        ((LabeledFigure) figure).updateModel();
      }
    }

    @Override// DrawingEditorListener
    public void figureRemoved(DrawingEditorEvent e) {
      Figure figure = e.getFigure();

      if (figure == null) {
        return;
      }

      ModelComponent model = figure.get(FigureConstants.MODEL);

      if (model == null) {
        return;
      }

      synchronized (model) {
        // The removed figure shouldn't react on changes of the origin any more.
        if (figure instanceof OriginChangeListener) {
          Origin ref = figure.get(FigureConstants.ORIGIN);

          if (ref != null) {
            ref.removeListener((OriginChangeListener) figure);
            figure.set(FigureConstants.ORIGIN, null);
          }
        }
        // Disassociate from blocks...
        removeFromAllBlocks(model);
        // ...and remove the object itself.
        ModelComponent folder = modelManager.getModel().getFolder(model);
        synchronized (folder) {
          removeModelComponent(folder, model);
        }
      }
    }

    @Override
    public void figureSelected(DrawingEditorEvent event) {
      if (event.getCount() == 0) {
        fComponentsTreeManager.selectItems(null);
        fBlocksTreeManager.selectItems(null);
      }
      else if (event.getCount() == 1) {
        // Single figure selected.
        Figure figure = event.getFigure();

        if (figure != null) {
          ModelComponent model = figure.get(FigureConstants.MODEL);

          if (model != null) {
            model.addAttributesChangeListener(attributesEventHandler);
            fPropertiesComponent.setModel(model);
            fComponentsTreeManager.selectItem(model);
            fBlocksTreeManager.selectItem(model);
          }
        }
      }
      else {
        // Multiple figures selected.
        List<ModelComponent> models = new LinkedList<>();
        Set<ModelComponent> components = new HashSet<>();

        for (Figure figure : event.getFigures()) {
          ModelComponent model = figure.get(FigureConstants.MODEL);
          if (model != null) {
            models.add(model);
            components.add(model);
          }
        }

        // Display shared properties of the selected figures.
        ModelComponent model = new PropertiesCollection(models);
        fComponentsTreeManager.selectItems(components);
        fBlocksTreeManager.selectItems(components);
        fPropertiesComponent.setModel(model);
      }
    }

    /**
     * Removes a component from all blocks in the model.
     *
     * @param model The component to be removed.
     */
    private void removeFromAllBlocks(ModelComponent model) {
      // The (invisible?) root folder of the "Blocks" tree...
      ModelComponent mainFolder
          = modelManager.getModel().getMainFolder(SystemModel.FolderKey.BLOCKS);

      synchronized (mainFolder) {
        // ... contains one folder for each Block

        for (ModelComponent blockModelComp : mainFolder.getChildComponents()) {
          BlockModel block = (BlockModel) blockModelComp;

          List<ModelComponent> elementsToRemove = new ArrayList<>();
          // All child components (Points, Paths) of one Block
          for (ModelComponent blockChildComp : block.getChildComponents()) {
            if (model == blockChildComp) {
              elementsToRemove.add(blockChildComp);
            }
          }

          if (!elementsToRemove.isEmpty()) {
            // At least one component found
            for (ModelComponent mc : elementsToRemove) {
              block.removeCourseElement(mc);
            }

            block.courseElementsChanged();
          }
        }
      }
    }
  }

  /**
   * MouseListener for vehicle dragging events in the tree view.
   */
  private class VehicleDragHandler
      extends MouseAdapter {

    /**
     * The cursor to be used when a vehicle is dragged.
     */
    private final Cursor dragCursor;
    /**
     * The currently selected/dragged vehicle model.
     */
    private VehicleModel vehicleModel;

    /**
     * Creates a new instance.
     *
     * @param dragCursor The cursor to be used when a vehicle is dragged.
     */
    public VehicleDragHandler(Cursor dragCursor) {
      this.dragCursor = requireNonNull(dragCursor, "dragCursor");
    }

    @Override
    public void mousePressed(MouseEvent e) {
      UserObject object = fComponentsTreeManager.getDraggedUserObject(e);

      if (object instanceof VehicleUserObject) {
        vehicleModel = ((VehicleUserObject) object).getModelComponent();
      }
      else {
        vehicleModel = null;
      }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
      if (vehicleModel == null) {
        return;
      }
      Point eOnScreen = e.getLocationOnScreen();
      for (OpenTCSDrawingView drawView : getDrawingViews()) {
        if (drawView.getComponent().isShowing()) {
          if (drawView.containsPointOnScreen(eOnScreen)) {
            drawView.setCursor(dragCursor);
          }
        }
      }

      fComponentsTreeManager.setCursor(dragCursor);
      setCursor(dragCursor);
    }

    @Override
    public void mouseReleased(MouseEvent event) {
      // Reset cursors to the default ones.
      fComponentsTreeManager.setCursor(Cursor.getDefaultCursor());
      setCursor(Cursor.getDefaultCursor());
      vehicleModel = null;

      if (vehicleModel != null && (Vehicle.ProcState) vehicleModel.getPropertyProcState().getValue() == Vehicle.ProcState.IDLE) {
        createOrderToPointOnScreen(event.getLocationOnScreen());
      }
    }

    // Class-specific methods start here.
    private void createOrderToPointOnScreen(Point locationOnScreen) {
      for (OpenTCSDrawingView drawView : getDrawingViews()) {
        drawView.setCursor(Cursor.getDefaultCursor());

        if (drawView.getComponent().isShowing()
            && drawView.containsPointOnScreen(locationOnScreen)) {
          Figure figure = getFigureAtPointInView(locationOnScreen, drawView);
          if (figure instanceof LabeledPointFigure) {
            createOrderToPointFigure((LabeledPointFigure) figure);
          }
        }
      }
    }

    private Figure getFigureAtPointInView(Point locationOnScreen,
                                          OpenTCSDrawingView drawView) {
      Point drawingViewOnScreen = drawView.getComponent().getLocationOnScreen();
      Point drawingViewPoint
          = new Point(locationOnScreen.x - drawingViewOnScreen.x,
                      locationOnScreen.y - drawingViewOnScreen.y);
      return drawView.findFigure(drawingViewPoint);
    }

    private void createOrderToPointFigure(LabeledPointFigure figure) {
      PointModel model = (PointModel) figure.get(FigureConstants.MODEL);
      orderUtil.createTransportOrder(model, vehicleModel);
    }
  }

  private class DrawingViewClosingListener
      implements CVetoClosingListener {

    private final DefaultSingleCDockable newDockable;

    public DrawingViewClosingListener(DefaultSingleCDockable newDockable) {
      this.newDockable = newDockable;
    }

    @Override
    public void closing(CVetoClosingEvent event) {
    }

    @Override
    public void closed(CVetoClosingEvent event) {
      // A dockable is closeable by default. It isn't closeable
      // when switching kernel states and we want to hide additional views
      if (newDockable.isCloseable()) {
        removeDrawingView(newDockable);
      }
    }
  }
}


<|start_filename|>openTCS-PeripheralCommAdapter-Loopback/src/main/java/org/opentcs/commadapter/peripheral/loopback/commands/EnableManualModeCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.commadapter.peripheral.loopback.commands;

import org.opentcs.commadapter.peripheral.loopback.LoopbackPeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;

/**
 * A command to enable/disable the comm adapter's manual mode.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class EnableManualModeCommand
    implements PeripheralAdapterCommand {

  /**
   * Whether to enable/disable manual mode.
   */
  private final boolean enabled;

  /**
   * Creates a new instance.
   *
   * @param enabled Whether to enable/disable manual mode.
   */
  public EnableManualModeCommand(boolean enabled) {
    this.enabled = enabled;
  }

  @Override
  public void execute(PeripheralCommAdapter adapter) {
    if (!(adapter instanceof LoopbackPeripheralCommAdapter)) {
      return;
    }

    LoopbackPeripheralCommAdapter loopbackAdapter = (LoopbackPeripheralCommAdapter) adapter;
    loopbackAdapter.enableManualMode(enabled);
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/PropertyTableModel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import javax.swing.table.AbstractTableModel;
import static org.opentcs.guing.plugins.panels.loadgenerator.I18nPlantOverviewPanelLoadGenerator.BUNDLE_PATH;

/**
 * Table model for transport order proerties.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class PropertyTableModel
    extends AbstractTableModel {

  /**
   * This classe's bundle.
   */
  private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_PATH);

  /**
   * The column names.
   */
  private static final String[] COLUMN_NAMES = new String[] {
    BUNDLE.getString("propertyTableModel.column_key.headerText"),
    BUNDLE.getString("propertyTableModel.column_value.headerText")
  };
  /**
   * The column classes.
   */
  private static final Class<?>[] COLUMN_CLASSES = new Class<?>[] {
    String.class,
    String.class
  };
  /**
   * The properties we're maintaining.
   */
  private List<PropEntry> data = new ArrayList<>();

  /**
   * Creates a new instance.
   *
   * @param data The properties.
   */
  public PropertyTableModel(Map<String, String> data) {
    requireNonNull(data, "data");

    for (Entry<String, String> entry : data.entrySet()) {
      this.data.add(new PropEntry(entry.getKey(), entry.getValue()));
    }
  }
  
  /**
   * Creates a new instance.
   */
  public PropertyTableModel() {
  }

  @Override
  public int getRowCount() {
    return data.size();
  }

  @Override
  public int getColumnCount() {
    return COLUMN_NAMES.length;
  }

  @Override
  public Object getValueAt(int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= data.size()) {
      return null;
    }
    PropEntry entry = data.get(rowIndex);

    switch (columnIndex) {
      case 0:
        return entry.getKey();
      case 1:
        return entry.getValue();
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  @Override
  public String getColumnName(int columnIndex) {
    return COLUMN_NAMES[columnIndex];
  }

  @Override
  public Class<?> getColumnClass(int columnIndex) {
    return COLUMN_CLASSES[columnIndex];
  }

  @Override
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    switch (columnIndex) {
      case 0:
        return true;
      case 1:
        return true;
      default:
        throw new IllegalArgumentException("Invalid columnIndex: " + columnIndex);
    }
  }

  @Override
  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if (rowIndex < 0 || rowIndex >= data.size()) {
      return;
    }
    PropEntry entry = data.get(rowIndex);

    if (aValue == null) {
      return;
    }
    switch (columnIndex) {
      case 0:
        entry.setKey((String) aValue);
        break;
      case 1:
        entry.setValue((String) aValue);
        break;
      default:
        throw new IllegalArgumentException("Unhandled columnIndex: " + columnIndex);
    }
  }

  /**
   * Returns this model's complete content.
   *
   * @return This model's complete content. The result list is unmodifiable.
   */
  public List<PropEntry> getList() {
    return Collections.unmodifiableList(data);
  }

  /**
   * Adds an entry to the end of the model/list.
   *
   * @param propEntry The new entry.
   */
  public void addData(PropEntry propEntry) {
    requireNonNull(propEntry, "propEntry");

    data.add(propEntry);
    fireTableDataChanged();
  }

  /**
   * Removes the entry at the given index.
   * Does nothing if <code>row</code> does not exist.
   *
   * @param row Index of entry to be removed.
   */
  public void removeData(int row) {
    if (row < 0 || row >= data.size()) {
      return;
    }
    data.remove(row);
    fireTableDataChanged();
  }

  /**
   * A class for editing properties.
   */
  public static class PropEntry {

    /**
     * The key.
     */
    private String key = "";
    /**
     * The value.
     */
    private String value = "";

    /**
     * Creates a new instance.
     */
    public PropEntry() {
    }

    /**
     * Creates a new PropEntry.
     *
     * @param key The key
     * @param value The value
     */
    public PropEntry(String key, String value) {
      this.key = requireNonNull(key, "key");
      this.value = requireNonNull(value, "value");
    }

    /**
     * Returns the key.
     *
     * @return The key
     */
    public String getKey() {
      return key;
    }

    /**
     * Sets the key.
     *
     * @param key The new key
     */
    public void setKey(String key) {
      this.key = requireNonNull(key, "key");
    }

    /**
     * Returns the value.
     *
     * @return The value
     */
    public String getValue() {
      return value;
    }

    /**
     * Sets the value.
     *
     * @param value The new value
     */
    public void setValue(String value) {
      this.value = requireNonNull(value, "value");
    }
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/SslParameterSet.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access;

import java.io.File;
import java.io.Serializable;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * A set of parameters to be used for SSL-encrypted socket connections.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class SslParameterSet
    implements Serializable {

  /**
   * The default type used for truststore and keystore files.
   */
  public static final String DEFAULT_KEYSTORE_TYPE = "PKCS12";

  /**
   * The type used for keystore and truststore.
   */
  private final String keystoreType;
  /**
   * The file path of the keystore.
   */
  private final File keystoreFile;
  /**
   * The password for the keystore file.
   */
  private final String keystorePassword;
  /**
   * The file path of the truststore.
   */
  private final File truststoreFile;
  /**
   * The password for the truststore file.
   */
  private final String truststorePassword;

  /**
   * Creates a new instance.
   *
   * @param keystoreType The type used for keystore and truststore
   * @param keystoreFile The keystore file
   * @param truststoreFile The truststore file
   * @param keystorePassword The keystore file password
   * @param truststorePassword The truststore file password
   */
  public SslParameterSet(@Nonnull String keystoreType,
                         @Nullable File keystoreFile,
                         @Nullable String keystorePassword,
                         @Nullable File truststoreFile,
                         @Nullable String truststorePassword) {
    this.keystoreType = requireNonNull(keystoreType, "keystoreType");
    this.keystoreFile = keystoreFile;
    this.keystorePassword = keystorePassword;
    this.truststoreFile = truststoreFile;
    this.truststorePassword = truststorePassword;
  }

  /**
   * Returns the keystoreType used to decrypt the keystore and truststore.
   *
   * @return The keystoreType used to decrypt the keystore and truststore
   */
  @Nonnull
  public String getKeystoreType() {
    return keystoreType;
  }

  /**
   * Returns the file path of the keystore file.
   *
   * @return The file path of the keystore file
   */
  @Nullable
  public File getKeystoreFile() {
    return keystoreFile;
  }

  /**
   * Returns the password for the keystore file.
   *
   * @return The password for the keystore file
   */
  @Nullable
  public String getKeystorePassword() {
    return keystorePassword;
  }

  /**
   * Returns the file path of the truststore file.
   *
   * @return The file path of the truststore file
   */
  @Nullable
  public File getTruststoreFile() {
    return truststoreFile;
  }

  /**
   * Returns the password for the truststore file.
   *
   * @return The password for the truststore file
   */
  @Nullable
  public String getTruststorePassword() {
    return truststorePassword;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/selection/vehicles/IsIdleAndDegraded.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.vehicles;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.selection.RechargeVehicleSelectionFilter;

/**
 * Filters vehicles that are idle and have a degraded energy level.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class IsIdleAndDegraded
    implements RechargeVehicleSelectionFilter {

  @Override
  public Collection<String> apply(Vehicle vehicle) {
    return idleAndDegraded(vehicle) ? new ArrayList<>() : Arrays.asList(getClass().getName());
  }

  private boolean idleAndDegraded(Vehicle vehicle) {
    return vehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_UTILIZED
        && vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && vehicle.hasState(Vehicle.State.IDLE)
        && vehicle.getCurrentPosition() != null
        && vehicle.getOrderSequence() == null
        && vehicle.isEnergyLevelDegraded();
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/RouterService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import org.opentcs.access.KernelRuntimeException;
import org.opentcs.components.kernel.Router;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Path;

/**
 * Provides methods concerning the {@link Router}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface RouterService {

  /**
   * Updates a path's lock state.
   *
   * @param ref A reference to the path to be updated.
   * @param locked Indicates whether the path is to be locked ({@code true}) or unlocked
   * ({@code false}).
   * @throws ObjectUnknownException If the referenced path does not exist.
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void updatePathLock(TCSObjectReference<Path> ref, boolean locked)
      throws ObjectUnknownException, KernelRuntimeException;

  /**
   * Notifies the router that the topology has changed in a significant way and needs to be
   * re-evaluated.
   *
   * @throws KernelRuntimeException In case there is an exception executing this method.
   */
  void updateRoutingTopology()
      throws KernelRuntimeException;
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/PeriodicVehicleRedispatchingTask.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching;

import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Periodically checks for idle vehicles that could process a transport order.
 * The main purpose of doing this is retrying to dispatch vehicles that were not in a dispatchable
 * state when dispatching them was last tried.
 * A potential reason for this is that a vehicle temporarily reported an error because a safety
 * sensor was triggered.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeriodicVehicleRedispatchingTask
    implements Runnable {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeriodicVehicleRedispatchingTask.class);

  private final DispatcherService dispatcherService;

  private final TCSObjectService objectService;

  /**
   * Creates a new instance.
   *
   * @param dispatcherService The dispatcher service used to dispatch vehicles.
   * @param objectService The object service.
   */
  @Inject
  public PeriodicVehicleRedispatchingTask(DispatcherService dispatcherService,
                                          TCSObjectService objectService) {
    this.dispatcherService = requireNonNull(dispatcherService, "dispatcherService");
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public void run() {
    // If there are any vehicles that could process a transport order,
    // trigger the dispatcher once.
    objectService.fetchObjects(Vehicle.class, this::couldProcessTransportOrder).stream()
        .findAny()
        .ifPresent(vehicle -> {
          LOG.debug("Vehicle {} could process transport order, triggering dispatcher ...", vehicle);
          dispatcherService.dispatch();
        });
  }

  private boolean couldProcessTransportOrder(Vehicle vehicle) {
    return vehicle.getIntegrationLevel() == Vehicle.IntegrationLevel.TO_BE_UTILIZED
        && vehicle.getCurrentPosition() != null
        && !vehicle.isEnergyLevelCritical()
        && (processesNoOrder(vehicle)
            || processesDispensableOrder(vehicle));
  }

  private boolean processesNoOrder(Vehicle vehicle) {
    return vehicle.hasProcState(Vehicle.ProcState.IDLE)
        && (vehicle.hasState(Vehicle.State.IDLE)
            || vehicle.hasState(Vehicle.State.CHARGING));
  }

  private boolean processesDispensableOrder(Vehicle vehicle) {
    return vehicle.hasProcState(Vehicle.ProcState.PROCESSING_ORDER)
        && objectService.fetchObject(TransportOrder.class, vehicle.getTransportOrder())
            .isDispensable();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/test/java/org/opentcs/guing/components/properties/type/MergedPropertySuggestionsTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.junit.*;
import static org.junit.Assert.*;
import org.opentcs.components.plantoverview.PropertySuggestions;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class MergedPropertySuggestionsTest {

  private PropertySuggestions instance1;
  private PropertySuggestions instance2;
  private PropertySuggestions emptyInstance;

  @Before
  public void setUp() {
    emptyInstance = new PropertySuggestionsImpl();

    instance1 = new PropertySuggestionsImpl();
    instance1.getKeySuggestions().add("key1");
    instance1.getKeySuggestions().add("key2");
    instance1.getKeySuggestions().add("key3");
    instance1.getKeySuggestions().add("doubleKeyTest");
    instance1.getValueSuggestions().add("value1");
    instance1.getValueSuggestions().add("value2");
    instance1.getValueSuggestions().add("value3");
    instance1.getValueSuggestions().add("doubleValueTest");

    instance2 = new PropertySuggestionsImpl();
    instance2.getKeySuggestions().add("doubleKeyTest");
    instance2.getKeySuggestions().add("key4");
    instance2.getKeySuggestions().add("key5");
    instance2.getKeySuggestions().add("key6");
    instance2.getValueSuggestions().add("doubleValueTest");
    instance2.getValueSuggestions().add("value1");
    instance2.getValueSuggestions().add("value2");
    instance2.getValueSuggestions().add("value3");
  }

  @Test
  public void shouldRemainEmptyForNoSuggestions() {
    MergedPropertySuggestions mergedSuggestions = new MergedPropertySuggestions(new HashSet<>());
    assertTrue(mergedSuggestions.getKeySuggestions().isEmpty());
    assertTrue(mergedSuggestions.getValueSuggestions().isEmpty());
  }

  @Test
  public void shouldRemainEmptyForEmptySuggestions() {
    Set<PropertySuggestions> sugSet = new HashSet<>(Arrays.asList(emptyInstance));
    MergedPropertySuggestions mergedSuggestions = new MergedPropertySuggestions(sugSet);
    assertTrue(mergedSuggestions.getKeySuggestions().isEmpty());
    assertTrue(mergedSuggestions.getValueSuggestions().isEmpty());
  }

  @Test
  public void shouldMergeSuggestions() {
    Set<PropertySuggestions> sugSet = new HashSet<>(Arrays.asList(instance1, instance2));
    MergedPropertySuggestions mergedSuggestions = new MergedPropertySuggestions(sugSet);
    assertEquals(Sets.union(instance1.getKeySuggestions(), instance2.getKeySuggestions()),
                 mergedSuggestions.getKeySuggestions());
    assertEquals(Sets.union(instance1.getValueSuggestions(), instance2.getValueSuggestions()),
                 mergedSuggestions.getValueSuggestions());
  }

  private class PropertySuggestionsImpl
      implements PropertySuggestions {

    private final Set<String> keySuggestions = new HashSet<>();
    private final Set<String> valueSuggestions = new HashSet<>();

    public PropertySuggestionsImpl() {

    }

    @Override
    public Set<String> getKeySuggestions() {
      return keySuggestions;
    }

    @Override
    public Set<String> getValueSuggestions() {
      return valueSuggestions;
    }

  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/dockable/DockingManagerModeling.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dockable;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JComponent;
import javax.swing.JFrame;
import org.opentcs.customizations.plantoverview.ApplicationFrame;
import org.opentcs.guing.components.layer.LayerGroupsPanel;
import org.opentcs.guing.components.layer.LayersPanel;
import org.opentcs.guing.components.properties.SelectionPropertiesComponent;
import org.opentcs.guing.components.tree.BlocksTreeViewManager;
import org.opentcs.guing.components.tree.ComponentsTreeViewManager;
import org.opentcs.guing.util.I18nPlantOverviewModeling;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * Utility class for working with dockables.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class DockingManagerModeling
    extends AbstractDockingManager {

  /**
   * ID for the tab pane, that contains the course, transport orders and order sequences.
   */
  public static final String COURSE_TAB_PANE_ID = "course_tab_pane";
  /**
   * ID for the tab pane, that contains the components, blocks and groups.
   */
  public static final String TREE_TAB_PANE_ID = "tree_tab_pane";
  public static final String LAYER_TAB_PANE_ID = "layer_tab_pane";
  public static final String COMPONENTS_ID = "comp_dock";
  public static final String BLOCKS_ID = "block_dock";
  public static final String PROPERTIES_ID = "properties_id";
  public static final String LAYERS_ID = "layers_id";
  public static final String LAYER_GROUPS_ID = "layer_groups_id";
  /**
   * The tree view manager for components.
   */
  private final ComponentsTreeViewManager componentsTreeViewManager;
  /**
   * The tree view manager for blocks.
   */
  private final BlocksTreeViewManager blocksTreeViewManager;
  /**
   * The panel displaying the properties of the currently selected driving course components.
   */
  private final SelectionPropertiesComponent selectionPropertiesComponent;
  /**
   * The panel displaying the layers in the plant model.
   */
  private final LayersPanel layersPanel;
  /**
   * The panel displaying the layer groups in the plant model.
   */
  private final LayerGroupsPanel layerGroupsPanel;
  /**
   * Tab pane that contains the components, blocks and groups.
   */
  private CStack treeTabPane;
  /**
   * Tab pane that contains the course, transport orders and order sequences.
   */
  private CStack courseTabPane;
  /**
   * Tab pane that contains layers and layer groups.
   */
  private CStack layerTabPane;

  /**
   * Creates a new instance.
   *
   * @param applicationFrame The application's main frame.
   * @param componentsTreeViewManager The tree view manager for components.
   * @param blocksTreeViewManager The tree view manager for blocks.
   * @param selectionPropertiesComponent The panel displaying the properties of the currently
   * selected driving course components.
   * @param layersPanel The panel displaying the layers in the plant model.
   * @param layerGroupsPanel The panel displaying the layer groups in the plant model.
   */
  @Inject
  public DockingManagerModeling(@ApplicationFrame JFrame applicationFrame,
                                ComponentsTreeViewManager componentsTreeViewManager,
                                BlocksTreeViewManager blocksTreeViewManager,
                                SelectionPropertiesComponent selectionPropertiesComponent,
                                LayersPanel layersPanel,
                                LayerGroupsPanel layerGroupsPanel) {
    super(new CControl(applicationFrame));
    this.componentsTreeViewManager = requireNonNull(componentsTreeViewManager,
                                                    "componentsTreeViewManager");
    this.blocksTreeViewManager = requireNonNull(blocksTreeViewManager, "blocksTreeViewManager");
    this.selectionPropertiesComponent = requireNonNull(selectionPropertiesComponent,
                                                       "selectionPropertiesComponent");
    this.layersPanel = requireNonNull(layersPanel, "layersPanel");
    this.layerGroupsPanel = requireNonNull(layerGroupsPanel, "layerGroupsPanel");
  }

  @Override
  public void reset() {
    removeDockable(BLOCKS_ID);
    removeDockable(COMPONENTS_ID);
    removeDockable(PROPERTIES_ID);
    removeDockable(LAYERS_ID);
    removeDockable(LAYER_GROUPS_ID);
    getCControl().removeStation(getTabPane(COURSE_TAB_PANE_ID));
    getCControl().removeStation(getTabPane(TREE_TAB_PANE_ID));
    getCControl().removeStation(getTabPane(LAYER_TAB_PANE_ID));
  }

  @Override
  public void initializeDockables() {
    getCControl().setGroupBehavior(CGroupBehavior.TOPMOST);

    // Disable keyboard shortcuts to avoid collisions.
    getCControl().putProperty(CControl.KEY_GOTO_NORMALIZED, null);
    getCControl().putProperty(CControl.KEY_GOTO_EXTERNALIZED, null);
    getCControl().putProperty(CControl.KEY_GOTO_MAXIMIZED, null);
    getCControl().putProperty(CControl.KEY_MAXIMIZE_CHANGE, null);

    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(I18nPlantOverviewModeling.DOCKABLE_PATH);
    CGrid grid = new CGrid(getCControl());
    courseTabPane = new CStack(COURSE_TAB_PANE_ID);
    addTabPane(COURSE_TAB_PANE_ID, courseTabPane);
    treeTabPane = new CStack(TREE_TAB_PANE_ID);
    addTabPane(TREE_TAB_PANE_ID, treeTabPane);
    layerTabPane = new CStack(LAYER_TAB_PANE_ID);
    addTabPane(LAYER_TAB_PANE_ID, layerTabPane);
    DefaultSingleCDockable treeViewDock
        = createDockable(COMPONENTS_ID,
                         bundle.getString("dockingManagerModeling.panel_components.title"),
                         (JComponent) componentsTreeViewManager.getTreeView(),
                         false);
    DefaultSingleCDockable treeBlocks
        = createDockable(BLOCKS_ID,
                         bundle.getString("dockingManagerModeling.panel_blocks.title"),
                         (JComponent) blocksTreeViewManager.getTreeView(),
                         false);

    grid.add(0, 0, 250, 400, treeTabPane);
    grid.add(0, 400, 250, 300,
             createDockable(PROPERTIES_ID,
                            bundle.getString("dockingManagerModeling.panel_properties.title"),
                            selectionPropertiesComponent,
                            false));
    DefaultSingleCDockable layersDock = 
             createDockable(LAYERS_ID,
                            bundle.getString("dockingManagerModeling.panel_layers.title"),
                            layersPanel,
                            false);
    DefaultSingleCDockable layerGroupsDock = 
             createDockable(LAYER_GROUPS_ID,
                            bundle.getString("dockingManagerModeling.panel_layerGroups.title"),
                            layerGroupsPanel,
                            false);
    grid.add(0, 700, 250, 300, layerTabPane);
    grid.add(400, 0, 1000, 500, courseTabPane);

    getCControl().getContentArea().deploy(grid);

    // init tab panes
    addTabTo(treeViewDock, TREE_TAB_PANE_ID, 0);
    addTabTo(treeBlocks, TREE_TAB_PANE_ID, 1);
    addTabTo(layersDock, LAYER_TAB_PANE_ID, 0);
    addTabTo(layerGroupsDock, LAYER_TAB_PANE_ID, 1);
    treeTabPane.getStation().setFrontDockable(treeViewDock.intern());
    layerTabPane.getStation().setFrontDockable(layersDock.intern());
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/util/ResourceBundleUtil.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 * Extended by IML: 1. Allow access to specific ResourceBundles 2. Different
 * icon sizes for menu / toolbar items
 *
 *
 * @(#)ResourceBundleUtil.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.util;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import static java.util.Objects.requireNonNull;
import java.util.ResourceBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is a convenience wrapper for accessing resources stored in a ResourceBundle.
 *
 * @author <NAME>, <NAME>0, CH-6405 Immensee, Switzerland
 * @author <NAME> (Fraunhofer IML)
 */
public class ResourceBundleUtil
    implements Serializable {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ResourceBundleUtil.class);
  /**
   * The global verbose property.
   */
  private static final boolean IS_VERBOSE = true;
  /**
   * The wrapped resource bundle.
   */
  private final ResourceBundle resource;
  /**
   * The base name of the resource bundle.
   */
  private final String baseName;

  /**
   * Creates a new ResouceBundleUtil which wraps the provided resource bundle.
   *
   * @param baseName
   * @param locale
   */
  public ResourceBundleUtil(String baseName, Locale locale) {
    this.baseName = requireNonNull(baseName, "baseName");
    requireNonNull(locale, "locale");
    this.resource = ResourceBundle.getBundle(baseName, locale);
  }

  /**
   * Get a String from the ResourceBundle. <br>Convenience method to save
   * casting.
   *
   * @param key The key of the property.
   * @return The value of the property. Returns the key if the property is
   * missing.
   */
  public String getString(String key) {
    try {
      return resource.getString(key);
    }
    catch (MissingResourceException e) {
      if (IS_VERBOSE) {
        LOG.warn("baseName: {}, '{}' not found.", baseName, key, e);
      }

      return key;
    }
  }

  /**
   * Returns a formatted string using javax.text.MessageFormat.
   *
   * @param key
   * @param arguments
   * @return formatted String
   */
  public String getFormatted(String key, Object... arguments) {
    return MessageFormat.format(getString(key), arguments);
  }

  public static ResourceBundleUtil getBundle(String baseName)
      throws MissingResourceException {
    return new ResourceBundleUtil(baseName, Locale.getDefault());
  }

  @Override
  public String toString() {
    return super.toString() + "[" + baseName + ", " + resource + "]";
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/commands/TriggerCommand.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.commands;

import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.virtualvehicle.LoopbackCommunicationAdapter;

/**
 * A command to trigger the comm adapter in single step mode.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TriggerCommand
    implements AdapterCommand {

  @Override
  public void execute(VehicleCommAdapter adapter) {
    if (!(adapter instanceof LoopbackCommunicationAdapter)) {
      return;
    }

    LoopbackCommunicationAdapter loopbackAdapter = (LoopbackCommunicationAdapter) adapter;
    loopbackAdapter.trigger();
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/util/ImageDirectory.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.util;

import javax.swing.ImageIcon;

/**
 * This utility class declares the main image directory.
 * It also provides utility methods to get the url to files in the directory.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public final class ImageDirectory {

  private ImageDirectory() {
  }

  /**
   * The directory where GUI images and icons are stored.
   */
  public static final String DIR = "/org/opentcs/guing/res/symbols";

  /**
   * Returns an ImageIcon from a relative path inside the image directory
   *
   * @param relPath path to file inside the image directory.
   * @return the new ImageIcon
   */
  public static ImageIcon getImageIcon(String relPath) {
    return new ImageIcon(ImageDirectory.class.getResource(DIR + relPath));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/services/InternalVehicleService.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.services;

import java.util.List;
import java.util.Set;
import org.opentcs.data.ObjectUnknownException;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;

/**
 * Declares the methods the vehicle service must provide which are not accessible to remote peers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface InternalVehicleService
    extends VehicleService {

  /**
   * Updates a vehicle's energy level.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param energyLevel The vehicle's new energy level.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleEnergyLevel(TCSObjectReference<Vehicle> ref, int energyLevel)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's load handling devices.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param devices The vehicle's new load handling devices.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleLoadHandlingDevices(TCSObjectReference<Vehicle> ref,
                                        List<LoadHandlingDevice> devices)
      throws ObjectUnknownException;

  /**
   * Updates the point which a vehicle is expected to occupy next.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param pointRef A reference to the point which the vehicle is expected to occupy next.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleNextPosition(TCSObjectReference<Vehicle> vehicleRef,
                                 TCSObjectReference<Point> pointRef)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's order sequence.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param sequenceRef A reference to the order sequence the vehicle processes.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleOrderSequence(TCSObjectReference<Vehicle> vehicleRef,
                                  TCSObjectReference<OrderSequence> sequenceRef)
      throws ObjectUnknownException;

  /**
   * Updates the vehicle's current orientation angle (-360..360 degrees, or {@link Double#NaN}, if
   * the vehicle doesn't provide an angle).
   *
   * @param ref A reference to the vehicle to be modified.
   * @param angle The vehicle's orientation angle.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleOrientationAngle(TCSObjectReference<Vehicle> ref, double angle)
      throws ObjectUnknownException;

  /**
   * Places a vehicle on a point.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param pointRef A reference to the point on which the vehicle is to be placed.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehiclePosition(TCSObjectReference<Vehicle> vehicleRef,
                             TCSObjectReference<Point> pointRef)
      throws ObjectUnknownException;

  /**
   * Updates the vehicle's current precise position in mm.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param position The vehicle's precise position in mm.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehiclePrecisePosition(TCSObjectReference<Vehicle> ref, Triple position)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's processing state.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param state The vehicle's new processing state.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleProcState(TCSObjectReference<Vehicle> ref, Vehicle.ProcState state)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's recharge operation.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param rechargeOperation The vehicle's new recharge action.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleRechargeOperation(TCSObjectReference<Vehicle> ref, String rechargeOperation)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's index of the last route step travelled for the current drive order of its
   * current transport order.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param index The new index.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleRouteProgressIndex(TCSObjectReference<Vehicle> ref, int index)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's claimed resources.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param resources The new resources.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleClaimedResources(TCSObjectReference<Vehicle> ref,
                                     List<Set<TCSResourceReference<?>>> resources)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's allocated resources.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param resources The new resources.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleAllocatedResources(TCSObjectReference<Vehicle> ref,
                                       List<Set<TCSResourceReference<?>>> resources)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's state.
   *
   * @param ref A reference to the vehicle to be modified.
   * @param state The vehicle's new state.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleState(TCSObjectReference<Vehicle> ref, Vehicle.State state)
      throws ObjectUnknownException;

  /**
   * Updates a vehicle's transport order.
   *
   * @param vehicleRef A reference to the vehicle to be modified.
   * @param orderRef A reference to the transport order the vehicle processes.
   * @throws ObjectUnknownException If the referenced vehicle does not exist.
   */
  void updateVehicleTransportOrder(TCSObjectReference<Vehicle> vehicleRef,
                                   TCSObjectReference<TransportOrder> orderRef)
      throws ObjectUnknownException;
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/batchcreator/OrderBatchCreator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.batchcreator;

import java.util.Set;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.data.order.TransportOrder;

/**
 * Declares the methods of transport order batch creators.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface OrderBatchCreator {

  /**
   * Creates a new transport order batch.
   *
   * @return The created transport orders
   * @throws KernelRuntimeException In case the kernel threw an exception when
   * creating the transport orders.
   */
  Set<TransportOrder> createOrderBatch()
      throws KernelRuntimeException;
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/data/model/visualization/ElementPropKeys.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.data.model.visualization;

/**
 * Defines some reserved/commonly used property keys of
 * {@link LayoutElement LayoutElements}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ElementPropKeys {

  /**
   * X coordinate at which the point is to be drawn (in mm).
   * Type: int.
   * Default value: Physical coordinate of the point.
   */
  String POINT_POS_X = "POSITION_X";
  /**
   * Y coordinate at which the point is to be drawn (in mm).
   * Type: int.
   * Default value: Physical coordinate of the point.
   */
  String POINT_POS_Y = "POSITION_Y";
  /**
   * X offset of the label's position to the object's position (in lu).
   * Type: int.
   * Default value: ??
   */
  String POINT_LABEL_OFFSET_X = "LABEL_OFFSET_X";
  /**
   * Y offset of the label's position to the object's position (in lu).
   * Type: int.
   * Default value: ??
   */
  String POINT_LABEL_OFFSET_Y = "LABEL_OFFSET_Y";
  /**
   * Orientation angle of the label (in degrees).
   * Type: int [0..360].
   * Default value: 0.
   */
  String POINT_LABEL_ORIENTATION_ANGLE = "LABEL_ORIENTATION_ANGLE";
  /**
   * X coordinate at which the location is to be drawn (in mm).
   * Type: int.
   * Default value: ??.
   */
  String LOC_POS_X = "POSITION_X";
  /**
   * Y coordinate at which the location is to be drawn (in mm).
   * Type: int.
   * Default value: ??.
   */
  String LOC_POS_Y = "POSITION_Y";
  /**
   * X offset of the label's position to the object's position (in lu).
   * Type: int.
   * Default value: ??
   */
  String LOC_LABEL_OFFSET_X = "LABEL_OFFSET_X";
  /**
   * Y offset of the label's position to the object's position (in lu).
   * Type: int.
   * Default value: ??
   */
  String LOC_LABEL_OFFSET_Y = "LABEL_OFFSET_Y";
  /**
   * Orientation angle of the label (in degrees).
   * Type: int [0..360].
   * Default value: 0.
   */
  String LOC_LABEL_ORIENTATION_ANGLE = "LABEL_ORIENTATION_ANGLE";
  /**
   * The drawing type of the path.
   * Type: String {Elbow, Slanted, Curved, Bezier, Direct}
   * Default value: DIRECT.
   */
  String PATH_CONN_TYPE = "CONN_TYPE";
  /**
   * Control points describing the way the connection is being drawn (if the
   * connection type is not Direct).
   * Type: String. (List of comma-separated X/Y pairs, with the pairs being
   * separated by semicola. Example: "x1,x1;x2,y2;x3,y3")
   * Default value: empty.
   */
  String PATH_CONTROL_POINTS = "CONTROL_POINTS";
  /**
   * Color in which block elements are to be emphasized.
   * Type: String (pattern: #rrggbb).
   * Default value: Automatically assigned.
   */
  String BLOCK_COLOR = "COLOR";
  /**
   * Color in which vehicle routes are to be emphasized.
   * Type: String (pattern: #rrggbb).
   * Default value: Color.RED
   */
  String VEHICLE_ROUTE_COLOR = "ROUTE_COLOR";
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/CompositeVehicleComparator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization;

import com.google.common.collect.Lists;
import java.util.Comparator;
import java.util.Map;
import javax.inject.Inject;
import org.opentcs.data.model.Vehicle;
import org.opentcs.strategies.basic.dispatching.DefaultDispatcherConfiguration;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorByEnergyLevel;
import org.opentcs.strategies.basic.dispatching.priorization.vehicle.VehicleComparatorByName;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A composite of all configured vehicle comparators.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CompositeVehicleComparator
    implements Comparator<Vehicle> {

  /**
   * A comparator composed of all configured comparators, in the configured order.
   */
  private final Comparator<Vehicle> compositeComparator;

  @Inject
  public CompositeVehicleComparator(DefaultDispatcherConfiguration configuration,
                                    Map<String, Comparator<Vehicle>> availableComparators) {
    // At the end, if all other comparators failed to see a difference, compare by energy level.
    // As the energy level of two distinct vehicles may still be the same, finally compare by name.
    // Add configured comparators before these two.
    Comparator<Vehicle> composite
        = new VehicleComparatorByEnergyLevel().thenComparing(new VehicleComparatorByName());

    for (String priorityKey : Lists.reverse(configuration.vehiclePriorities())) {
      Comparator<Vehicle> configuredComparator = availableComparators.get(priorityKey);
      checkArgument(configuredComparator != null, "Unknown vehicle priority key: %s", priorityKey);
      composite = configuredComparator.thenComparing(composite);
    }
    this.compositeComparator = composite;
  }

  @Override
  public int compare(Vehicle o1, Vehicle o2) {
    return compositeComparator.compare(o1, o2);
  }

}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/action/app/AboutAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.app;

import java.awt.Component;
import java.awt.event.ActionEvent;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.AbstractAction;
import static javax.swing.Action.LARGE_ICON_KEY;
import static javax.swing.Action.MNEMONIC_KEY;
import static javax.swing.Action.SMALL_ICON;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import org.opentcs.access.SharedKernelServicePortalProvider;
import org.opentcs.customizations.plantoverview.ApplicationFrame;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.OpenTCSView;
import static org.opentcs.guing.util.I18nPlantOverviewOperating.MENU_PATH;
import org.opentcs.guing.util.ImageDirectory;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.Environment;

/**
 * Displays a dialog showing information about the application.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class AboutAction
    extends AbstractAction {

  /**
   * This action's ID.
   */
  public final static String ID = "application.about";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);
  /**
   * Stores the application's current state.
   */
  private final ApplicationState appState;
  /**
   * Provides access to a portal.
   */
  private final SharedKernelServicePortalProvider portalProvider;
  /**
   * The parent component for dialogs shown by this action.
   */
  private final Component dialogParent;

  /**
   * Creates a new instance.
   *
   * @param appState Stores the application's current state.
   * @param portalProvider Provides access to a portal.
   * @param dialogParent The parent component for dialogs shown by this action.
   */
  @Inject
  public AboutAction(ApplicationState appState,
                     SharedKernelServicePortalProvider portalProvider,
                     @ApplicationFrame Component dialogParent) {
    this.appState = requireNonNull(appState, "appState");
    this.portalProvider = requireNonNull(portalProvider, "portalProvider");
    this.dialogParent = requireNonNull(dialogParent, "dialogParent");

    putValue(NAME, BUNDLE.getString("aboutAction.name"));
    putValue(MNEMONIC_KEY, Integer.valueOf('A'));

    ImageIcon icon = ImageDirectory.getImageIcon("/menu/help-contents.png");
    putValue(SMALL_ICON, icon);
    putValue(LARGE_ICON_KEY, icon);
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    JOptionPane.showMessageDialog(
        dialogParent,
        "<html><p><b>" + OpenTCSView.NAME + "</b><br> "
        + BUNDLE.getFormatted("aboutAction.optionPane_applicationInformation.message.baselineVersion", Environment.getBaselineVersion()) + "<br>"
        + BUNDLE.getFormatted("aboutAction.optionPane_applicationInformation.message.customization",
                              Environment.getCustomizationName(),
                              Environment.getCustomizationVersion()) + "<br>"
        + BUNDLE.getString("aboutAction.optionPane_applicationInformation.message.copyright") + "<br>"
        + BUNDLE.getString("aboutAction.optionPane_applicationInformation.message.runningOn") + "<br>"
        + "Java: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + "<br>"
        + "JVM: " + System.getProperty("java.vm.version") + ", " + System.getProperty("java.vm.vendor") + "<br>"
        + "OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version") + ", " + System.getProperty("os.arch") + "<br>"
        + "<b>Kernel</b><br>"
        + portalProvider.getPortalDescription()
        + "<br>" + BUNDLE.getFormatted("aboutAction.optionPane_applicationInformation.message.mode", appState.getOperationMode())
        + "</p></html>",
        BUNDLE.getString("aboutAction.optionPane_applicationInformation.title"),
        JOptionPane.PLAIN_MESSAGE,
        new ImageIcon(getClass().getResource("/org/opentcs/guing/res/symbols/openTCS/openTCS.300x132.gif")));
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/rmi/factories/SocketFactoryProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.rmi.factories;

import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import javax.annotation.Nullable;

/**
 * A provider for instances of {@link RMIClientSocketFactory} and {@link RMIServerSocketFactory}.
 * Generally one provider should provide compatible factories for clients and servers.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface SocketFactoryProvider {

  /**
   * Returns a {@link RMIClientSocketFactory}.
   *
   * @return A {@link RMIClientSocketFactory}.
   * May be <code>null</code> to indicate that a default factory implementation is to be used.
   */
  @Nullable
  RMIClientSocketFactory getClientSocketFactory();

  /**
   * Returns a {@link RMIServerSocketFactory}.
   *
   * @return A {@link RMIServerSocketFactory}.
   * May be <code>null</code> to indicate that a default factory implementation is to be used.
   */
  @Nullable
  RMIServerSocketFactory getServerSocketFactory();
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/AboutDialog.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter;

import java.awt.Frame;
import javax.swing.JDialog;
import org.opentcs.util.Environment;

/**
 * An about dialog.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class AboutDialog
    extends JDialog {

  /**
   * Creates new AboutDialog.
   *
   * @param parent The parent frame.
   * @param modal Whether the dialog blocks user input to other top-level windows when shown.
   */
  public AboutDialog(Frame parent, boolean modal) {
    super(parent, modal);
    initComponents();
  }

  // CHECKSTYLE:OFF
  /**
   * This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    logoPanel = new javax.swing.JPanel();
    opentcsLogoLbl = new javax.swing.JLabel();
    contactPanel = new javax.swing.JPanel();
    opentcsContactPanel = new javax.swing.JPanel();
    opentcsLbl = new javax.swing.JLabel();
    versionLbl = new javax.swing.JLabel();
    versionTxtLbl = new javax.swing.JLabel();
    customVersionLbl = new javax.swing.JLabel();
    customVersionTxtLbl = new javax.swing.JLabel();
    homepageLbl = new javax.swing.JLabel();
    homepageTxtLbl = new javax.swing.JLabel();
    emailLbl = new javax.swing.JLabel();
    emailTxtLbl = new javax.swing.JLabel();
    imlPanel = new javax.swing.JPanel();
    fraunhoferImlLbl = new javax.swing.JLabel();
    homepageImlLbl = new javax.swing.JLabel();
    homepageImlTxtLbl = new javax.swing.JLabel();
    fillingLbl = new javax.swing.JLabel();
    closeButton = new javax.swing.JButton();
    fillingLbl2 = new javax.swing.JLabel();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/kernelcontrolcenter/Bundle"); // NOI18N
    setTitle(bundle.getString("aboutDialog.title")); // NOI18N
    setResizable(false);
    getContentPane().setLayout(new java.awt.GridBagLayout());

    logoPanel.setBackground(new java.awt.Color(255, 255, 255));
    logoPanel.setLayout(new java.awt.BorderLayout());

    opentcsLogoLbl.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
    opentcsLogoLbl.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/opentcs/kernelcontrolcenter/res/logos/opentcs.gif"))); // NOI18N
    logoPanel.add(opentcsLogoLbl, java.awt.BorderLayout.CENTER);

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.ipadx = 6;
    gridBagConstraints.ipady = 6;
    getContentPane().add(logoPanel, gridBagConstraints);

    contactPanel.setLayout(new javax.swing.BoxLayout(contactPanel, javax.swing.BoxLayout.Y_AXIS));

    opentcsContactPanel.setLayout(new java.awt.GridBagLayout());

    opentcsLbl.setFont(opentcsLbl.getFont().deriveFont(opentcsLbl.getFont().getStyle() | java.awt.Font.BOLD));
    opentcsLbl.setText("open Transportation Control System");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
    opentcsContactPanel.add(opentcsLbl, gridBagConstraints);

    versionLbl.setText(bundle.getString("aboutDialog.label_baselineVersion.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    opentcsContactPanel.add(versionLbl, gridBagConstraints);

    versionTxtLbl.setText(Environment.getBaselineVersion());
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
    opentcsContactPanel.add(versionTxtLbl, gridBagConstraints);

    customVersionLbl.setText(bundle.getString("aboutDialog.label_customVersion.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    opentcsContactPanel.add(customVersionLbl, gridBagConstraints);

    customVersionTxtLbl.setText(Environment.getCustomizationName() + " " + Environment.getCustomizationVersion());
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
    opentcsContactPanel.add(customVersionTxtLbl, gridBagConstraints);

    homepageLbl.setText(bundle.getString("aboutDialog.label_homepage.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    opentcsContactPanel.add(homepageLbl, gridBagConstraints);

    homepageTxtLbl.setText("https://www.opentcs.org/");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
    opentcsContactPanel.add(homepageTxtLbl, gridBagConstraints);

    emailLbl.setText(bundle.getString("aboutDialog.label_email.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    opentcsContactPanel.add(emailLbl, gridBagConstraints);

    emailTxtLbl.setText("<EMAIL>");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
    opentcsContactPanel.add(emailTxtLbl, gridBagConstraints);

    contactPanel.add(opentcsContactPanel);

    imlPanel.setLayout(new java.awt.GridBagLayout());

    fraunhoferImlLbl.setFont(fraunhoferImlLbl.getFont().deriveFont(fraunhoferImlLbl.getFont().getStyle() | java.awt.Font.BOLD));
    fraunhoferImlLbl.setText(bundle.getString("aboutDialog.label_fraunhoferIml.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.gridwidth = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
    imlPanel.add(fraunhoferImlLbl, gridBagConstraints);

    homepageImlLbl.setText(bundle.getString("aboutDialog.label_homepage.text")); // NOI18N
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    imlPanel.add(homepageImlLbl, gridBagConstraints);

    homepageImlTxtLbl.setText("http://www.iml.fraunhofer.de/");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
    imlPanel.add(homepageImlTxtLbl, gridBagConstraints);

    contactPanel.add(imlPanel);

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    getContentPane().add(contactPanel, gridBagConstraints);

    fillingLbl.setText(" ");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weighty = 1.0;
    getContentPane().add(fillingLbl, gridBagConstraints);

    closeButton.setText(bundle.getString("aboutDialog.button_close.text")); // NOI18N
    closeButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        closeButtonActionPerformed(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    getContentPane().add(closeButton, gridBagConstraints);

    fillingLbl2.setText(" ");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 4;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weighty = 1.0;
    getContentPane().add(fillingLbl2, gridBagConstraints);

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
    this.setVisible(false);
  }//GEN-LAST:event_closeButtonActionPerformed
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton closeButton;
  private javax.swing.JPanel contactPanel;
  private javax.swing.JLabel customVersionLbl;
  private javax.swing.JLabel customVersionTxtLbl;
  private javax.swing.JLabel emailLbl;
  private javax.swing.JLabel emailTxtLbl;
  private javax.swing.JLabel fillingLbl;
  private javax.swing.JLabel fillingLbl2;
  private javax.swing.JLabel fraunhoferImlLbl;
  private javax.swing.JLabel homepageImlLbl;
  private javax.swing.JLabel homepageImlTxtLbl;
  private javax.swing.JLabel homepageLbl;
  private javax.swing.JLabel homepageTxtLbl;
  private javax.swing.JPanel imlPanel;
  private javax.swing.JPanel logoPanel;
  private javax.swing.JPanel opentcsContactPanel;
  private javax.swing.JLabel opentcsLbl;
  private javax.swing.JLabel opentcsLogoLbl;
  private javax.swing.JLabel versionLbl;
  private javax.swing.JLabel versionTxtLbl;
  // End of variables declaration//GEN-END:variables
  // CHECKSTYLE:ON
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/action/file/UploadModelToKernelAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.file;

import java.awt.event.ActionEvent;
import java.util.Objects;
import javax.swing.AbstractAction;
import static javax.swing.Action.ACCELERATOR_KEY;
import static javax.swing.Action.MNEMONIC_KEY;
import javax.swing.KeyStroke;
import org.opentcs.guing.application.OpenTCSView;
import static org.opentcs.guing.util.I18nPlantOverviewModeling.MENU_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 * An action to upload the (local) model to the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class UploadModelToKernelAction
    extends AbstractAction {

  public static final String ID = "file.uploadModelToKernel";

  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(MENU_PATH);

  private final OpenTCSView openTCSView;

  /**
   * Creates a new instance.
   *
   * @param openTCSView The openTCS view
   */
  public UploadModelToKernelAction(OpenTCSView openTCSView) {
    this.openTCSView = Objects.requireNonNull(openTCSView);

    putValue(NAME, BUNDLE.getString("uploadModelToKernelAction.name"));
    putValue(SHORT_DESCRIPTION, BUNDLE.getString("uploadModelToKernelAction.shortDescription"));
    putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt P"));
    putValue(MNEMONIC_KEY, Integer.valueOf('P'));

  }

  @Override
  public void actionPerformed(ActionEvent e) {
    openTCSView.uploadModelToKernel();
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/peripherals/jobs/PeripheralJobsContainerPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.peripherals.jobs;

import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableRowSorter;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.peripherals.PeripheralJob;
import static org.opentcs.guing.util.I18nPlantOverviewOperating.PERIPHERALJOB_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;
import org.opentcs.util.gui.StringTableCellRenderer;

/**
 * Shows a table of the kernel's peripheral jobs.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralJobsContainerPanel
    extends JPanel {

  /**
   * Maintains a set of all peripheral jobs existing on the kernel side.
   */
  private final PeripheralJobsContainer peripheralJobsContainer;
  /**
   * The table showing the peripheral jobs.
   */
  private JTable table;
  /**
   * The table's model.
   */
  private PeripheralJobTableModel tableModel;

  /**
   * Creates a new instance.
   *
   * @param peripheralJobsContainer Maintains a set of all peripheral jobs existing on the kernel
   * side.
   */
  @Inject
  public PeripheralJobsContainerPanel(PeripheralJobsContainer peripheralJobsContainer) {
    this.peripheralJobsContainer = requireNonNull(peripheralJobsContainer,
                                                  "peripheralJobsContainer");

    initComponents();
  }

  /**
   * Initializes this panel's contents.
   */
  public void initView() {
    tableModel.containerInitialized(peripheralJobsContainer.getPeripheralJobs());
  }

  private void initComponents() {
    setLayout(new BorderLayout());
    initPeripheralJobTable();
    add(new JScrollPane(table), BorderLayout.CENTER);
  }

  private void initPeripheralJobTable() {
    tableModel = new PeripheralJobTableModel();
    peripheralJobsContainer.addListener(tableModel);
    table = new JTable(tableModel);

    TableRowSorter<PeripheralJobTableModel> sorter = new TableRowSorter<>(tableModel);
    // Sort the table by the creation instant.
    sorter.setSortKeys(Arrays.asList(
        new RowSorter.SortKey(PeripheralJobTableModel.COLUMN_CREATION_TIME, SortOrder.DESCENDING)
    ));
    // ...but prevent manual sorting.
    for (int i = 0; i < table.getColumnCount(); i++) {
      sorter.setSortable(i, false);
    }
    sorter.setSortsOnUpdates(true);
    table.setRowSorter(sorter);

    // Hide the column that shows the creation time.
    table.removeColumn(table.getColumnModel()
        .getColumn(table.convertColumnIndexToView(PeripheralJobTableModel.COLUMN_CREATION_TIME)));

    TableCellRenderer renderer = new StringTableCellRenderer<TCSObjectReference>(reference -> {
      if (reference == null) {
        return "-";
      }

      return reference.getName();
    });
    table.getColumnModel().getColumn(PeripheralJobTableModel.COLUMN_RELATED_VEHICLE)
        .setCellRenderer(renderer);
    table.getColumnModel().getColumn(PeripheralJobTableModel.COLUMN_RELATED_ORDER)
        .setCellRenderer(renderer);

    table.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent evt) {
        if (evt.getButton() == MouseEvent.BUTTON1) {
          if (evt.getClickCount() == 2) {
            showSelectedJob();
          }
        }

        if (evt.getButton() == MouseEvent.BUTTON3) {
          if (table.getSelectedRow() != -1) {
            showPopupMenuForSelectedJob(evt.getX(), evt.getY());
          }
        }
      }
    });
  }

  private void showSelectedJob() {
    int rowIndex = table.getSelectedRow();
    if (rowIndex > -1) {
      PeripheralJob selectedJob = tableModel.getEntryAt(table.convertRowIndexToModel(rowIndex));
      // TODO Show a dialog with details about the selected job
    }

  }

  private void showPopupMenuForSelectedJob(int x, int y) {
    boolean singleRowSelected = table.getSelectedRowCount() <= 1;
    ResourceBundleUtil bundle = ResourceBundleUtil.getBundle(PERIPHERALJOB_PATH);
    JPopupMenu menu = new JPopupMenu();
    JMenuItem item = menu.add(bundle.getString("peripheralJobsContainerPanel.table_peripheralJobs.popupMenuItem_showDetails.text"));
    item.setEnabled(singleRowSelected);
    item.addActionListener(event -> showSelectedJob());

    menu.show(table, x, y);
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/exchange/adapter/PointAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.exchange.adapter;

import static java.util.Objects.requireNonNull;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.access.to.model.PointCreationTO;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObject;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Triple;
import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.components.properties.type.AngleProperty;
import org.opentcs.guing.components.properties.type.CoordinateProperty;
import org.opentcs.guing.components.properties.type.LengthProperty;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.LayoutModel;
import org.opentcs.guing.model.elements.PointModel;

/**
 * An adapter for points.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @author <NAME> (Fraunhofer IML)
 */
public class PointAdapter
    extends AbstractProcessAdapter {

  @Override  // OpenTCSProcessAdapter
  public void updateModelProperties(TCSObject<?> tcsObject,
                                    ModelComponent modelComponent,
                                    SystemModel systemModel,
                                    TCSObjectService objectService) {
    Point point = requireNonNull((Point) tcsObject, "tcsObject");
    PointModel model = (PointModel) modelComponent;

    // Name
    model.getPropertyName().setText(point.getName());

    // Position in model
    model.getPropertyModelPositionX().setValueAndUnit(point.getPosition().getX(),
                                                      LengthProperty.Unit.MM);
    model.getPropertyModelPositionY().setValueAndUnit(point.getPosition().getY(),
                                                      LengthProperty.Unit.MM);
    model.getPropertyVehicleOrientationAngle()
        .setValueAndUnit(point.getVehicleOrientationAngle(), AngleProperty.Unit.DEG);

    updateModelType(model, point);
    updateMiscModelProperties(model, point);
    updateModelLayoutProperties(model, point, systemModel.getLayoutModel());
  }

  @Override
  public PlantModelCreationTO storeToPlantModel(ModelComponent modelComponent,
                                                SystemModel systemModel,
                                                PlantModelCreationTO plantModel) {
    PlantModelCreationTO result = plantModel
        .withPoint(
            new PointCreationTO(modelComponent.getName())
                .withPosition(getKernelCoordinates((PointModel) modelComponent))
                .withVehicleOrientationAngle(getKernelVehicleAngle((PointModel) modelComponent))
                .withType(getKernelPointType((PointModel) modelComponent))
                .withProperties(getKernelProperties(modelComponent))
                .withLayout(getLayout((PointModel) modelComponent))
        );

    unmarkAllPropertiesChanged(modelComponent);

    return result;
  }

  private void updateModelLayoutProperties(PointModel model, Point point, LayoutModel layoutModel) {
    model.getPropertyLayoutPosX().setText(String.valueOf(point.getLayout().getPosition().getX()));
    model.getPropertyLayoutPosY().setText(String.valueOf(point.getLayout().getPosition().getY()));
    model.getPropertyPointLabelOffsetX()
        .setText(String.valueOf(point.getLayout().getLabelOffset().getX()));
    model.getPropertyPointLabelOffsetY()
        .setText(String.valueOf(point.getLayout().getLabelOffset().getY()));
    LayerWrapper layerWrapper = layoutModel.getPropertyLayerWrappers()
        .getValue().get(point.getLayout().getLayerId());
    model.getPropertyLayerWrapper().setValue(layerWrapper);
  }

  private void updateModelType(PointModel model, Point point) {
    PointModel.Type value;

    switch (point.getType()) {
      case PARK_POSITION:
        value = PointModel.Type.PARK;
        break;
      case REPORT_POSITION:
        value = PointModel.Type.REPORT;
        break;
      case HALT_POSITION:
      default:
        value = PointModel.Type.HALT;
    }

    model.getPropertyType().setValue(value);
  }

  private Point.Type getKernelPointType(PointModel model) {
    return convertPointType((PointModel.Type) model.getPropertyType().getValue());
  }

  private Triple getKernelCoordinates(PointModel model) {
    return convertToTriple(model.getPropertyModelPositionX(),
                           model.getPropertyModelPositionY());
  }

  private double getKernelVehicleAngle(PointModel model) {
    return model.getPropertyVehicleOrientationAngle().getValueByUnit(AngleProperty.Unit.DEG);
  }

  private PointCreationTO.Layout getLayout(PointModel model) {
    return new PointCreationTO.Layout(
        new Couple(Long.parseLong(model.getPropertyLayoutPosX().getText()),
                   Long.parseLong(model.getPropertyLayoutPosY().getText())),
        new Couple(Long.parseLong(model.getPropertyPointLabelOffsetX().getText()),
                   Long.parseLong(model.getPropertyPointLabelOffsetY().getText())),
        model.getPropertyLayerWrapper().getValue().getLayer().getId()
    );
  }

  private Point.Type convertPointType(PointModel.Type type) {
    requireNonNull(type, "type");
    switch (type) {
      case PARK:
        return Point.Type.PARK_POSITION;
      case REPORT:
        return Point.Type.REPORT_POSITION;
      case HALT:
        return Point.Type.HALT_POSITION;
      default:
        throw new IllegalArgumentException("Unhandled type: " + type);
    }
  }

  private Triple convertToTriple(CoordinateProperty cpx, CoordinateProperty cpy) {
    Triple result = new Triple((int) cpx.getValueByUnit(LengthProperty.Unit.MM),
                               (int) cpy.getValueByUnit(LengthProperty.Unit.MM),
                               0);

    return result;
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/dialogs/InputValidationListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dialogs;

/**
 * A Listener Interface, instances can handle validation of the user input.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface InputValidationListener {

  /**
   * Notifies about the validity of an input.
   *
   * @param success true if input is valid, false otherwise.
   */
  void inputValidationSuccessful(boolean success);
}


<|start_filename|>openTCS-Kernel-Extension-RMI-Services/src/main/java/org/opentcs/kernel/extensions/rmi/DefaultUserAccountProvider.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.extensions.rmi;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import org.opentcs.common.GuestUserCredentials;

/**
 * The default impelementation of {@link UserAccountProvider}.
 * Provides only one (guest) user account.
 *
 * @see GuestUserCredentials
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultUserAccountProvider
    implements UserAccountProvider {

  public DefaultUserAccountProvider() {
  }

  @Override
  public Set<UserAccount> getUserAccounts() {
    return new HashSet<>(Arrays.asList(new UserAccount(GuestUserCredentials.USER,
                                                       GuestUserCredentials.PASSWORD,
                                                       EnumSet.allOf(UserPermission.class))));
  }
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/InputPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.LinkedList;
import java.util.List;

/**
 * Base class for panels that provide input methods for the user and can be
 * embedded in an {@link InputDialog}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class InputPanel
    extends javax.swing.JPanel {

  /**
   * Object to store the user's input. Must be explicitly set via captureInput()
   * or doReset(). What exactly this input is depends on the actual
   * implementation of InputPanel's subclass.
   */
  protected Object input;
  /**
   * If true, the panel's state/input can be reset via doReset() to a default
   * value.
   * By default <code>InputPanels</code> are not resetable.
   */
  protected boolean resetable;
  /**
   * List of ValidationListeners that will receive ValidationEvents.
   */
  private final List<ValidationListener> validationListeners = new LinkedList<>();
  /**
   * Title of the panel. Might be used by the surrounding dialog.
   */
  private final String title;
  /**
   * Indicates whether the current user input is valid.
   * If the panel validates the input this can be changed via setInputValid().
   */
  private boolean inputValid = true;

  /**
   * Create a new instance of InputPanel.
   * @param title The title of this panel.
   */
  public InputPanel(String title) {
    this.title = title;
  }

  /**
   * Get the title of this panel. 
   * @return The title
   */
  public String getTitle() {
    return title;
  }

  /**
   * Add a {@link ValidationListener} that will receive 
   * {@link ValidationEvent ValidationEvents}
   * whenever the validity of the input in this panel changes. The 
   * {@link ValidationListener} will receive a {@link ValidationEvent} with the
   * current validity state immediately after beeing added.
   * If the panel does not validate it's input the validity will never change.
   * @param listener The {@link ValidationListener}
   */
  public void addValidationListener(ValidationListener listener) {
    validationListeners.add(listener);
    // Fire initial validation event for this listener
    listener.validityChanged(new ValidationEvent(this, inputValid));
  }

  /**
   * Mark the input of the panel as valid/invalid and send 
   * {@link ValidationEvent ValidationEvents}
   * to the attached {@link ValidationListener ValidationListeners}.
   * The Validity should only be changed via this method!
   * @param valid true, if input is valid. false otherwise.
   */
  protected void setInputValid(boolean valid) {
    boolean changed = valid != inputValid;
    inputValid = valid;
    if (changed) {
      ValidationEvent e = new ValidationEvent(this, valid);
      for (ValidationListener l : validationListeners) {
        l.validityChanged(e);
      }
    }
  }
/**
 * 
 * @return The validation Listeners.
 */
  public List<ValidationListener> getValidationListeners() {
    return validationListeners;
  }

  /**
   * Determine if the current input in the panel is valid.
   * If the input isn't validated this will always return <code>true</code>.
   * @see #addValidationListener
   * @return <code>true</code> if input is valid, <code>false</code> otherwise.
   */
  public boolean isInputValid() {
    return inputValid;
  }

  /**
   * Get the user input from the panel. If the input wasn't captured before
   * (see {@link #captureInput()}) null is returned. Otherwise it depends on the 
   * concrete implementing panel what the input can look like.
   * @return The input
   */
  public Object getInput() {
    return input;
  }

  /**
   * Tells the panel to get and store the user input which will be available
   * via {@link #getInput()} afterwards.
   * Usually this method should be called from the enclosing dialog when the
   * ok button is pressed. It is not intended to be used by the user of the 
   * panel!
   */
  protected abstract void captureInput();

  /**
   * Returns whether the content of this panel can be reset to a default value.
   * If the panel is resetable the enclosing dialog might want to show a reset
   * button.
   * @see #doReset()
   * @return panel is resetable?
   */
  public boolean isResetable() {
    return resetable;
  }

  /**
   * Inform the panel, that it should reset it's input values (probably because
   * the reset button in the enclosing dialog was pressed).
   * It's up to the specific panel itself to decide what is resetted. 
   * The default implementation does nothing.
   * It should be overwritten in subclasses if reset functionality is needed.
   */
  public void doReset() {
    // Do nothing here.
  }

  /**
   * <p>
   * An interface that can be used to implement the builder-pattern
   * (see Joshua Bloch's <i>Effective Java</i>).
   * <br>
   * As an <code>InputPanel</code> might have many required and/or optional
   * parameters it can be more convinient to use a Builder class instead of
   * public constructors.
   * A builder should implement a public constructor with required parameters
   * for the panel and public setters for optional parameters.
   * The <code>InputPanel</code> is created by the {@link #build} method.
   * <br>
   * For an example implementation see {@link SingleTextInputPanel.Builder}.
   * </p>
   * <p>
   * <b>Usage</b>:
   * </p>
   * <ol>
   * <li>Instanciate the builder, passing required parameters to the 
   * constructor.</li>
   * <li>Set optional parameters via the other public methods.</li>
   * <li>Actually build the panel according to the previously specified 
   * parameters using the build() method.</li>
   * </ol>
   * <p>
   * <b>Note</b>: 
   * The parameter methods should always return the builder itself, so the 
   * creation of a panel can be done in a single statement (see the 
   * <i>Builder-Pattern</i> in Joshua Bloch's <i>Effective Java</i>).
   * </p>
   */
  public interface Builder {

    /**
     * Finally build the {@link InputPanel} as described by this 
     * <code>Builder</code>.
     * @return The created <code>InputPanel</code>.
     */
    InputPanel build();
  }
}


<|start_filename|>openTCS-Kernel/src/test/java/org/opentcs/kernel/workingset/PrefixedUlidObjectNameProviderTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.workingset;

import com.google.common.collect.Ordering;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import org.junit.*;
import org.opentcs.access.to.CreationTO;

/**
 * Tests for a {@link PrefixedUlidObjectNameProvider}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PrefixedUlidObjectNameProviderTest {

  private PrefixedUlidObjectNameProvider nameProvider;

  @Before
  public void setUp() {
    this.nameProvider = new PrefixedUlidObjectNameProvider();
  }

  @Test
  public void shouldUsePrefixFromCreationTO() {
    assertThat(nameProvider.apply(new CreationTO("SomeName-")), startsWith("SomeName-"));
  }

  @Test
  public void shouldAppendSuffix() {
    assertThat(nameProvider.apply(new CreationTO("")), is(not("")));
  }

  @Test
  public void shouldProvideNamesInChronologicalOrder() {
    final int count = 100000;
    final CreationTO to = new CreationTO("SomeName-");

    List<String> namesInOrderOfCreation = new ArrayList<>(count);
    for (int i = 0; i < count; i++) {
      namesInOrderOfCreation.add(nameProvider.apply(to));
    }

    List<String> namesLexicographic = Ordering.natural().sortedCopy(namesInOrderOfCreation);

    assertThat(namesInOrderOfCreation, is(equalTo(namesLexicographic)));
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/transportorder/TransportOrderComparatorByName.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.transportorder;

import java.util.Comparator;
import org.opentcs.data.order.TransportOrder;

/**
 * Compares {@link TransportOrder}s by their names.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class TransportOrderComparatorByName
    implements Comparator<TransportOrder> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "BY_NAME";

  @Override
  public int compare(TransportOrder order1, TransportOrder order2) {
    return order1.getName().compareTo(order2.getName());
  }

}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/LayerWrapperProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.opentcs.guing.components.layer.LayerWrapper;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property that contains a {@link LayerWrapper} instance.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LayerWrapperProperty
    extends AbstractComplexProperty {

  /**
   * Creates a new instance.
   *
   * @param model The model component.
   * @param value The layer wrapper.
   */
  public LayerWrapperProperty(ModelComponent model, LayerWrapper value) {
    super(model);
    fValue = value;
  }

  @Override
  public Object getComparableValue() {
    return getValue().getLayer().getId();
  }

  @Override
  public String toString() {
    return getValue().getLayer().getName();
  }

  @Override
  public void copyFrom(Property property) {
    LayerWrapperProperty layerWrapperProperty = (LayerWrapperProperty) property;
    setValue(layerWrapperProperty.getValue());
  }

  @Override
  public LayerWrapper getValue() {
    return (LayerWrapper) super.getValue();
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/KernelStateOperating.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel;

import com.google.common.util.concurrent.Uninterruptibles;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.opentcs.access.Kernel;
import org.opentcs.components.kernel.Dispatcher;
import org.opentcs.components.kernel.KernelExtension;
import org.opentcs.components.kernel.PeripheralJobDispatcher;
import org.opentcs.components.kernel.Router;
import org.opentcs.components.kernel.Scheduler;
import org.opentcs.components.kernel.services.InternalVehicleService;
import org.opentcs.customizations.kernel.ActiveInOperatingMode;
import org.opentcs.customizations.kernel.GlobalSyncObject;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Vehicle;
import org.opentcs.kernel.extensions.controlcenter.vehicles.AttachmentManager;
import org.opentcs.kernel.peripherals.LocalPeripheralControllerPool;
import org.opentcs.kernel.peripherals.PeripheralAttachmentManager;
import org.opentcs.kernel.persistence.ModelPersister;
import org.opentcs.kernel.vehicles.LocalVehicleControllerPool;
import org.opentcs.kernel.workingset.Model;
import org.opentcs.kernel.workingset.PeripheralJobPool;
import org.opentcs.kernel.workingset.TCSObjectPool;
import org.opentcs.kernel.workingset.TransportOrderPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class implements the standard openTCS kernel in normal operation.
 *
 * @author <NAME> (Fraunhofer IML)
 */
class KernelStateOperating
    extends KernelStateOnline {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(KernelStateOperating.class);
  /**
   * The kernel application's configuration.
   */
  private final KernelApplicationConfiguration configuration;
  /**
   * The order facade to the object pool.
   */
  private final TransportOrderPool orderPool;
  /**
   * The peripheral job facade to the object pool.
   */
  private final PeripheralJobPool jobPool;
  /**
   * This kernel's router.
   */
  private final Router router;
  /**
   * This kernel's scheduler.
   */
  private final Scheduler scheduler;
  /**
   * This kernel's dispatcher.
   */
  private final Dispatcher dispatcher;
  /**
   * This kernel's peripheral job dispatcher.
   */
  private final PeripheralJobDispatcher peripheralJobDispatcher;
  /**
   * A pool of vehicle controllers.
   */
  private final LocalVehicleControllerPool vehicleControllerPool;
  /**
   * A pool of peripheral controllers.
   */
  private final LocalPeripheralControllerPool peripheralControllerPool;
  /**
   * The kernel's executor.
   */
  private final ScheduledExecutorService kernelExecutor;
  /**
   * A task for periodically getting rid of old orders.
   */
  private final OrderCleanerTask orderCleanerTask;
  /**
   * This kernel state's local extensions.
   */
  private final Set<KernelExtension> extensions;
  /**
   * The kernel's attachment manager.
   */
  private final AttachmentManager attachmentManager;
  /**
   * The kernel's peripheral attachment manager.
   */
  private final PeripheralAttachmentManager peripheralAttachmentManager;
  /**
   * The vehicle service.
   */
  private final InternalVehicleService vehicleService;
  /**
   * A handle for the cleaner task.
   */
  private ScheduledFuture<?> cleanerTaskFuture;
  /**
   * This instance's <em>initialized</em> flag.
   */
  private boolean initialized;

  /**
   * Creates a new KernelStateOperating.
   *
   * @param globalSyncObject kernel threads' global synchronization object.
   * @param objectPool The object pool to be used.
   * @param model The model to be used
   * @param orderPool The transport order pool to be used.
   * @param jobPool The peripheral job pool top be used.
   * @param modelPersister The model persister to be used.
   * @param configuration This class's configuration.
   * @param router The router to be used.
   * @param scheduler The scheduler to be used.
   * @param dispatcher The dispatcher to be used.
   * @param peripheralJobDispatcher The peripheral job dispatcher to be used.
   * @param controllerPool The vehicle controller pool to be used.
   * @param peripheralControllerPool The peripheral controller pool to be used.
   * @param kernelExecutor The kernel executer to be used.
   * @param orderCleanerTask The order cleaner task to be used.
   * @param extensions The kernel extensions to load.
   * @param attachmentManager The attachment manager to be used.
   * @param peripheralAttachmentManager The peripheral attachment manager to be used.
   * @param vehicleService The vehicle service to be used.
   */
  @Inject
  KernelStateOperating(@GlobalSyncObject Object globalSyncObject,
                       TCSObjectPool objectPool,
                       Model model,
                       TransportOrderPool orderPool,
                       PeripheralJobPool jobPool,
                       ModelPersister modelPersister,
                       KernelApplicationConfiguration configuration,
                       Router router,
                       Scheduler scheduler,
                       Dispatcher dispatcher,
                       PeripheralJobDispatcher peripheralJobDispatcher,
                       LocalVehicleControllerPool controllerPool,
                       LocalPeripheralControllerPool peripheralControllerPool,
                       @KernelExecutor ScheduledExecutorService kernelExecutor,
                       OrderCleanerTask orderCleanerTask,
                       @ActiveInOperatingMode Set<KernelExtension> extensions,
                       AttachmentManager attachmentManager,
                       PeripheralAttachmentManager peripheralAttachmentManager,
                       InternalVehicleService vehicleService) {
    super(globalSyncObject,
          objectPool,
          model,
          modelPersister,
          configuration.saveModelOnTerminateOperating());
    this.orderPool = requireNonNull(orderPool, "orderPool");
    this.jobPool = requireNonNull(jobPool, "jobPool");
    this.configuration = requireNonNull(configuration, "configuration");
    this.router = requireNonNull(router, "router");
    this.scheduler = requireNonNull(scheduler, "scheduler");
    this.dispatcher = requireNonNull(dispatcher, "dispatcher");
    this.peripheralJobDispatcher = requireNonNull(peripheralJobDispatcher,
                                                  "peripheralJobDispatcher");
    this.vehicleControllerPool = requireNonNull(controllerPool, "controllerPool");
    this.peripheralControllerPool = requireNonNull(peripheralControllerPool,
                                                   "peripheralControllerPool");
    this.kernelExecutor = requireNonNull(kernelExecutor, "kernelExecutor");
    this.orderCleanerTask = requireNonNull(orderCleanerTask, "orderCleanerTask");
    this.extensions = requireNonNull(extensions, "extensions");
    this.attachmentManager = requireNonNull(attachmentManager, "attachmentManager");
    this.peripheralAttachmentManager = requireNonNull(peripheralAttachmentManager,
                                                      "peripheralAttachmentManager");
    this.vehicleService = requireNonNull(vehicleService, "vehicleService");
  }

  // Implementation of interface Kernel starts here.
  @Override
  public void initialize() {
    if (initialized) {
      LOG.debug("Already initialized.");
      return;
    }
    LOG.debug("Initializing operating state...");

    // Reset vehicle states to ensure vehicles are not dispatchable initially.
    for (Vehicle curVehicle : vehicleService.fetchObjects(Vehicle.class)) {
      vehicleService.updateVehicleProcState(curVehicle.getReference(), Vehicle.ProcState.IDLE);
      vehicleService.updateVehicleIntegrationLevel(curVehicle.getReference(),
                                                   Vehicle.IntegrationLevel.TO_BE_RESPECTED);
      vehicleService.updateVehicleState(curVehicle.getReference(), Vehicle.State.UNKNOWN);
      vehicleService.updateVehicleTransportOrder(curVehicle.getReference(), null);
      vehicleService.updateVehicleOrderSequence(curVehicle.getReference(), null);
    }

    LOG.debug("Initializing scheduler '{}'...", scheduler);
    scheduler.initialize();
    LOG.debug("Initializing router '{}'...", router);
    router.initialize();
    LOG.debug("Initializing dispatcher '{}'...", dispatcher);
    dispatcher.initialize();
    LOG.debug("Initializing peripheral job dispatcher '{}'...", peripheralJobDispatcher);
    peripheralJobDispatcher.initialize();
    LOG.debug("Initializing vehicle controller pool '{}'...", vehicleControllerPool);
    vehicleControllerPool.initialize();
    LOG.debug("Initializing peripheral controller pool '{}'...", peripheralControllerPool);
    peripheralControllerPool.initialize();
    LOG.debug("Initializing attachment manager '{}'...", attachmentManager);
    attachmentManager.initialize();
    LOG.debug("Initializing peripheral attachment manager '{}'...", peripheralAttachmentManager);
    peripheralAttachmentManager.initialize();

    // Start a task for cleaning up old orders periodically.
    cleanerTaskFuture = kernelExecutor.scheduleAtFixedRate(orderCleanerTask,
                                                           orderCleanerTask.getSweepInterval(),
                                                           orderCleanerTask.getSweepInterval(),
                                                           TimeUnit.MILLISECONDS);

    // Start kernel extensions.
    for (KernelExtension extension : extensions) {
      LOG.debug("Initializing kernel extension '{}'...", extension);
      extension.initialize();
    }
    LOG.debug("Finished initializing kernel extensions.");

    initialized = true;

    LOG.debug("Operating state initialized.");
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!initialized) {
      LOG.debug("Not initialized.");
      return;
    }
    LOG.debug("Terminating operating state...");
    super.terminate();

    // Terminate everything that may still use resources.
    for (KernelExtension extension : extensions) {
      LOG.debug("Terminating kernel extension '{}'...", extension);
      extension.terminate();
    }
    LOG.debug("Terminated kernel extensions.");

    // No need to clean up any more - it's all going to be cleaned up very soon.
    cleanerTaskFuture.cancel(false);
    cleanerTaskFuture = null;

    // Terminate strategies.
    LOG.debug("Terminating peripheral job dispatcher '{}'...", peripheralJobDispatcher);
    peripheralJobDispatcher.terminate();
    LOG.debug("Terminating dispatcher '{}'...", dispatcher);
    dispatcher.terminate();
    LOG.debug("Terminating router '{}'...", router);
    router.terminate();
    LOG.debug("Terminating scheduler '{}'...", scheduler);
    scheduler.terminate();
    LOG.debug("Terminating peripheral controller pool '{}'...", peripheralControllerPool);
    peripheralControllerPool.terminate();
    LOG.debug("Terminating vehicle controller pool '{}'...", vehicleControllerPool);
    vehicleControllerPool.terminate();
    LOG.debug("Terminating attachment manager '{}'...", attachmentManager);
    attachmentManager.terminate();
    LOG.debug("Terminating peripheral attachment manager '{}'...", peripheralAttachmentManager);
    peripheralAttachmentManager.terminate();
    // Grant communication adapters etc. some time to settle things.
    Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);

    // Ensure that vehicles do not reference orders any more.
    for (Vehicle curVehicle : vehicleService.fetchObjects(Vehicle.class)) {
      vehicleService.updateVehicleProcState(curVehicle.getReference(), Vehicle.ProcState.IDLE);
      vehicleService.updateVehicleIntegrationLevel(curVehicle.getReference(),
                                                   Vehicle.IntegrationLevel.TO_BE_RESPECTED);
      vehicleService.updateVehicleState(curVehicle.getReference(), Vehicle.State.UNKNOWN);
      vehicleService.updateVehicleTransportOrder(curVehicle.getReference(), null);
      vehicleService.updateVehicleOrderSequence(curVehicle.getReference(), null);
    }

    // Remove all orders and order sequences from the pool.
    orderPool.clear();
    // Remove all peripheral jobs from the pool.
    jobPool.clear();

    initialized = false;

    LOG.debug("Operating state terminated.");
  }

  @Override
  public Kernel.State getState() {
    return Kernel.State.OPERATING;
  }
}


<|start_filename|>openTCS-PlantOverview-Panel-LoadGenerator/src/main/java/org/opentcs/guing/plugins/panels/loadgenerator/batchcreator/RandomOrderBatchCreator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.plugins.panels.loadgenerator.batchcreator;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Random;
import java.util.Set;
import org.opentcs.access.KernelRuntimeException;
import org.opentcs.access.to.order.DestinationCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.data.model.Location;
import org.opentcs.data.order.DriveOrder.Destination;
import org.opentcs.data.order.TransportOrder;

/**
 * Randomly creates batches of transport orders.
 * Destinations and operations chosen are random and not guaranteed to work in
 * a real plant.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class RandomOrderBatchCreator
    implements OrderBatchCreator {

  /**
   * The transport order sergice we talk to.
   */
  private final TransportOrderService transportOrderService;
  /**
   * The dispatcher service.
   */
  private final DispatcherService dispatcherService;
  /**
   * The number of transport orders per batch.
   */
  private final int batchSize;
  /**
   * The number of drive orders per transport order.
   */
  private final int orderSize;
  /**
   * The locations in the model.
   */
  private final List<Location> locations;
  /**
   * A random number generator for selecting locations and operations.
   */
  private final Random random = new Random();

  /**
   * Creates a new RandomOrderBatchCreator.
   *
   * @param transportOrderService The transport order service.
   * @param dispatcherService The dispatcher service.
   * @param batchSize The number of transport orders per batch.
   * @param orderSize The number of drive orders per transport order.
   */
  public RandomOrderBatchCreator(TransportOrderService transportOrderService,
                                 DispatcherService dispatcherService,
                                 int batchSize,
                                 int orderSize) {
    this.transportOrderService = requireNonNull(transportOrderService, "transportOrderService");
    this.dispatcherService = requireNonNull(dispatcherService, "dispatcherService");
    this.batchSize = batchSize;
    this.orderSize = orderSize;
    locations = new ArrayList<>(transportOrderService.fetchObjects(Location.class));
  }

  @Override
  public Set<TransportOrder> createOrderBatch()
      throws KernelRuntimeException {
    Set<TransportOrder> createdOrders = new HashSet<>();
    if (locations.isEmpty()) {
      return createdOrders;
    }
    for (int i = 0; i < batchSize; i++) {
      createdOrders.add(createSingleOrder());
    }

    dispatcherService.dispatch();

    return createdOrders;
  }

  private TransportOrder createSingleOrder()
      throws KernelRuntimeException {
    List<DestinationCreationTO> dests = new ArrayList<>();
    for (int j = 0; j < orderSize; j++) {
      Location destLoc = locations.get(random.nextInt(locations.size()));
      dests.add(new DestinationCreationTO(destLoc.getName(), Destination.OP_NOP));
    }
    TransportOrder newOrder = transportOrderService.createTransportOrder(
        new TransportOrderCreationTO("TOrder-", dests).withIncompleteName(true)
    );

    return newOrder;
  }
}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/components/kernel/routing/Edge.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.components.kernel.routing;

import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.data.model.Path;

/**
 * A wrapper for {@link Path}s that can be used to build routing graphs.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class Edge {

  /**
   * The path in the model that is traversed on this edge.
   */
  private final Path path;
  /**
   * Whether the path is travelled in reverse direction.
   */
  private final boolean travellingReverse;

  /**
   * Creates a new instance.
   *
   * @param modelPath The path in the model that is traversed on this edge.
   * @param travellingReverse Whether the path is travelled in reverse direction.
   */
  public Edge(@Nonnull Path modelPath, boolean travellingReverse) {
    this.path = requireNonNull(modelPath, "modelPath");
    this.travellingReverse = travellingReverse;
  }

  /**
   * Returns the path in the model that is traversed on this edge.
   *
   * @return The path in the model that is traversed on this edge.
   */
  public Path getPath() {
    return path;
  }

  /**
   * Indicates whether the path is travelled in reverse direction.
   *
   * @return Whether the path is travelled in reverse direction.
   */
  public boolean isTravellingReverse() {
    return travellingReverse;
  }

  @Override
  public String toString() {
    return "Edge{"
        + "path=" + path + ", "
        + "travellingReverse=" + travellingReverse
        + '}';
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/thirdparty/jhotdraw/components/drawing/AbstractOpenTCSDrawingView.java<|end_filename|>
/**
 * (c): IML, JHotDraw.
 *
 *
 * Extended by IML: 1. Show Blocks and Pathes as overlay 2. Switch labels on/off
 *
 * @(#)DefaultDrawingView.java
 *
 * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
 * contributors. All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with the copyright holders. For details
 * see accompanying license terms.
 */
package org.opentcs.thirdparty.jhotdraw.components.drawing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import org.jhotdraw.draw.AbstractFigure;
import org.jhotdraw.draw.DefaultDrawingView;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.GridConstrainer;
import org.jhotdraw.draw.event.CompositeFigureEvent;
import org.jhotdraw.draw.event.FigureEvent;
import org.jhotdraw.gui.datatransfer.ClipboardUtil;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.OperationMode;
import org.opentcs.guing.components.EditableComponent;
import org.opentcs.guing.components.drawing.BezierLinerEditHandler;
import org.opentcs.guing.components.drawing.OffsetListener;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.components.drawing.course.Origin;
import org.opentcs.guing.components.drawing.figures.BitmapFigure;
import org.opentcs.guing.components.drawing.figures.LabeledFigure;
import org.opentcs.guing.components.drawing.figures.OriginFigure;
import org.opentcs.guing.components.drawing.figures.PathConnection;
import org.opentcs.guing.components.drawing.figures.SimpleLineConnection;
import org.opentcs.guing.components.drawing.figures.TCSLabelFigure;
import org.opentcs.guing.event.SystemModelTransitionEvent;
import org.opentcs.guing.model.SystemModel;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.ModelComponentUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A DrawingView implementation for the openTCS plant overview.
 *
 */
public abstract class AbstractOpenTCSDrawingView
    extends DefaultDrawingView
    implements OpenTCSDrawingView,
               EditableComponent,
               PropertyChangeListener {

  public static final String FOCUS_GAINED = "focusGained";
  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(AbstractOpenTCSDrawingView.class);
  /**
   * Stores the application's current state.
   */
  private final ApplicationState appState;
  /**
   * The manager keeping/providing the currently loaded model.
   */
  private final ModelManager modelManager;
  /**
   * This listener sets the position of the invisible offsetFigure after the
   * frame was resized.
   */
  private ComponentListener offsetListener;
  /**
   * Flag whether the labels shall be drawn.
   */
  private boolean labelsVisible = true;
  /**
   * A pointer to a figure that shall be highlighted by a red circle.
   */
  private Figure fFocusFigure;
  /**
   * Prohibits a loop in repaint().
   */
  private boolean doRepaint = true;
  /**
   * Background figures set to this DrawingView.
   */
  private final List<BitmapFigure> bitmapFigures = new ArrayList<>();
  /**
   * Handles edits of bezier liners.
   */
  private final BezierLinerEditHandler bezierLinerEditHandler = new BezierLinerEditHandler();

  /**
   * Creates new instance.
   *
   * @param appState Stores the application's current state.
   * @param modelManager Provides the current system model.
   */
  public AbstractOpenTCSDrawingView(ApplicationState appState, ModelManager modelManager) {
    this.appState = requireNonNull(appState, "appState");
    this.modelManager = requireNonNull(modelManager, "modelManager");

    // Set a dummy tool tip text to turn tooltips on
    setToolTipText(" ");
    setBackground(Color.LIGHT_GRAY);
    setAutoscrolls(true);
    GridConstrainer gridConstrainer = new ExtendedGridConstrainer(10, 10);
    gridConstrainer.setMajorGridSpacing(10);
    setVisibleConstrainer(gridConstrainer);
    setConstrainerVisible(true);
  }

  // ###
  // Methods of EventHandler start here.
  // ###
  @Override
  public void onEvent(Object event) {
    if (event instanceof SystemModelTransitionEvent) {
      handleSystemModelTransition((SystemModelTransitionEvent) event);
    }
  }

  // ###
  // Methods of PropertyChangeListener start here.
  // ###
  @Override // PropertyChangeListener
  public void propertyChange(PropertyChangeEvent evt) {
  }

  // ###
  // Methods of DrawingView start here.
  // ###
  @Override // DrawingView
  public void setDrawing(Drawing newValue) {
    Drawing oldValue = this.getDrawing();

    if (oldValue != null) {
      oldValue.removeUndoableEditListener(bezierLinerEditHandler);
    }
    if (newValue != null) {
      SystemModel model = modelManager.getModel();
      if (model != null) {
        Origin origin = model.getDrawingMethod().getOrigin();
        OriginFigure originFigure = origin.getFigure();
        if (!newValue.contains(originFigure)) {
          newValue.add(originFigure);
        }
      }

      newValue.addUndoableEditListener(bezierLinerEditHandler);
    }

    super.setDrawing(newValue);
  }

  @Override
  public OpenTCSDrawingEditor getEditor() {
    return (OpenTCSDrawingEditor) super.getEditor();
  }

  @Override // DrawingView
  public void addToSelection(Figure figure) {
    refreshDetailLevel();

    super.addToSelection(figure);

    getEditor().figuresSelected(new ArrayList<>(getSelectedFigures()));
    repaint();
  }

  @Override // DrawingView
  public void addToSelection(Collection<Figure> figures) {
    refreshDetailLevel();

    super.addToSelection(figures);
  }

  @Override // DrawingView
  public void removeFromSelection(Figure figure) {
    super.removeFromSelection(figure);

    // The OpenTCSDrawingEditor may be null here, although it shouldn't.
    // A possible explanation at the moment is: When restoring the default
    // layout all drawing views are removed and recreated. Currently this also
    // means that all bitmap figures are removed, which fire an event to all
    // listeners, that they were removed. It seems that one of the
    // removed drawing views receives this event. It may be possible
    // JHotDraw just didn't remove the view from the listener list.
    if (getEditor() != null) {
      getEditor().figuresSelected(new ArrayList<>(getSelectedFigures()));
      repaint();
    }
  }

  @Override // DrawingView
  public void selectAll() {
    super.selectAll();
    getEditor().figuresSelected(new ArrayList<>(getSelectedFigures()));
  }

  @Override // DrawingView
  public void clearSelection() {
    super.clearSelection();

    if (getSelectionCount() > 0) {
      getEditor().figuresSelected(new ArrayList<>(getSelectedFigures()));
    }
  }

  @Override // DrawingView
  public void setScaleFactor(final double newValue) {
    if (newValue == getScaleFactor()) {
      return;
    }

    // Save the (drawing) coordinates of the current center point to jump back to there after the
    // zoom.
    Rectangle2D.Double visibleViewRect = viewToDrawing(getVisibleRect());
    final int centerX = (int) (visibleViewRect.getCenterX() + 0.5);
    final int centerY = (int) -(visibleViewRect.getCenterY() + 0.5);
    for (BitmapFigure bmFigure : bitmapFigures) {
      bmFigure.setScaleFactor(getScaleFactor(), newValue);
    }

    SwingUtilities.invokeLater(() -> {
      super.setScaleFactor(newValue);
      scrollTo(centerX, centerY);
    });
  }

  @Override // DrawingView
  public void addNotify(DrawingEditor editor) {
    addOffsetListener((OpenTCSDrawingEditor) editor);

    super.addNotify(editor);
  }

  @Override // DrawingView
  public void removeNotify(DrawingEditor editor) {
    // XXX Is setting the scale factor (to invalidate the handles) really necessary?
    setScaleFactor(getScaleFactor());

    super.removeNotify(editor);
  }

  // ###
  // Methods of JComponent start here.
  // ###
  @Override
  public void processKeyEvent(KeyEvent e) {
    if ((e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0) {
      // Cut, copy, paste and duplicate
      if (e.getKeyCode() == KeyEvent.VK_X
          || e.getKeyCode() == KeyEvent.VK_C
          || e.getKeyCode() == KeyEvent.VK_V
          || e.getKeyCode() == KeyEvent.VK_D) {
        if (!appState.hasOperationMode(OperationMode.MODELLING)) {
          return;
        }
        processCutPasteKeyEvent();
      }
    }

    super.processKeyEvent(e);
  }

  // ###
  // Methods not declared in interfaces or superclasses start here.
  // ###
  @Override
  public void drawingOptionsChanged() {
    repaintDrawingArea();
  }

  private void repaintDrawingArea() {
    // We need to add the visible rect to the dirty area before we repaint.
    repaintDrawingArea(viewToDrawing(getVisibleRect()));
  }

  @Override
  public boolean isLabelsVisible() {
    return labelsVisible;
  }

  @Override
  public void setLabelsVisible(boolean newValue) {
    labelsVisible = newValue;

    if (getDrawing() == null) {
      return;
    }

    for (Figure figure : getDrawing().getChildren()) {
      if (figure instanceof LabeledFigure) {
        LabeledFigure lf = (LabeledFigure) figure;
        lf.setLabelVisible(newValue);
      }
    }
    // Repaint the whole layout.
    repaintDrawingArea();
  }

  /**
   * Returns the background images for this drawing view.
   *
   * @return List containing the associated bitmap figures.
   */
  public List<BitmapFigure> getBackgroundBitmaps() {
    return bitmapFigures;
  }

  @Override
  public void addBackgroundBitmap(File file) {
    addBackgroundBitmap(new BitmapFigure(file));
  }

  @Override
  public void addBackgroundBitmap(BitmapFigure bitmapFigure) {
    bitmapFigures.add(bitmapFigure);
    getDrawing().add(bitmapFigure);
    getDrawing().sendToBack(bitmapFigure);
  }

  @Override
  public void scrollTo(Figure figure) {
    if (figure == null) {
      return;
    }

    fFocusFigure = figure;

    scrollRectToVisible(computeVisibleRectangleForFigure(figure));

    repaint();
  }

  @Override
  public void updateBlock(BlockModel block) {
    for (Figure figure : ModelComponentUtil.getChildFigures(block, modelManager.getModel())) {
      ((AbstractFigure) figure).fireFigureChanged();
    }
  }

  @Override
  public boolean containsPointOnScreen(Point p) {
    return (p.x >= getLocationOnScreen().x && p.x < (getLocationOnScreen().x + getWidth())
            && p.y >= getLocationOnScreen().y && p.y < (getLocationOnScreen().y + getHeight()));
  }

  @Override
  public void zoomViewToWindow() {
    // 1. Zoom to 100%
    setScaleFactor(1.0);
    // 2. Zoom delayed
    SwingUtilities.invokeLater(
        () -> setScaleFactor(computeZoomLevelToDisplayAllFigures(getDrawing()))
    );
  }

  @Override
  protected void drawDrawing(Graphics2D gr) {
    if (getDrawing() == null) {
      return;
    }

    Graphics2D g2d = (Graphics2D) gr.create();
    AffineTransform tx = g2d.getTransform();
    tx.translate(getDrawingToViewTransform().getTranslateX(),
                 getDrawingToViewTransform().getTranslateY());
    tx.scale(getScaleFactor(), getScaleFactor());
    g2d.setTransform(tx);

    getDrawing().setFontRenderContext(g2d.getFontRenderContext());
    try {
      getDrawing().draw(g2d);
    }
    catch (ConcurrentModificationException e) {
      LOG.warn("Exception from JHotDraw caught while calling DefaultDrawing.draw(), continuing.");
      // TODO What to do when it is catched?
    }

    g2d.dispose();
  }

  private void handleSystemModelTransition(SystemModelTransitionEvent evt) {
    switch (evt.getStage()) {
      case UNLOADING:
        removeAll();
        break;
      default:
      // Do nada.
    }
  }

  private void processCutPasteKeyEvent() {
    List<Figure> selectedFigures = new CopyOnWriteArrayList<>(getSelectedFigures());

    for (Figure figure : selectedFigures) {
      if (figure instanceof SimpleLineConnection) {
        // A Path may only be selected if the connected start and end Points are selected, too
        SimpleLineConnection lineConnection = (SimpleLineConnection) figure;
        Figure startFigure = lineConnection.getStartFigure();
        Figure endFigure = lineConnection.getEndFigure();

        if (!selectedFigures.contains(startFigure)
            || !selectedFigures.contains(endFigure)) {
          removeFromSelection(figure);
        }
      }
    }

    if (getSelectedFigures().isEmpty()) {
      ClipboardUtil.getClipboard().setContents(new Transferable() {

        @Override
        public DataFlavor[] getTransferDataFlavors() {
          return new DataFlavor[0];
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
          return false;
        }

        @Override
        public Object getTransferData(DataFlavor flavor) {
          throw new UnsupportedOperationException("Not supported yet.");
        }
      }, null);
    }
  }

  /**
   * Moves the view so that the given points will be in the middle of the
   * drawing.
   *
   * @param xCenter The x coord that shall be in the middle.
   * @param yCenter The y coord that shall be in the middle.
   */
  private void scrollTo(final int xCenter, final int yCenter) {
    SwingUtilities.invokeLater(() -> {
      Point2D.Double pCenterView = new Point2D.Double(xCenter, -yCenter); // Vorzeichen!
      Point pCenterDrawing = drawingToView(pCenterView);
      JViewport viewport = (JViewport) getParent();
      int xUpperLeft = pCenterDrawing.x - viewport.getSize().width / 2;
      int yUpperLeft = pCenterDrawing.y - viewport.getSize().height / 2;
      Point pUpperLeft = new Point(xUpperLeft, yUpperLeft);
      Rectangle rCenter = new Rectangle(pUpperLeft, viewport.getSize());
      scrollRectToVisible(rCenter);
    });
  }

  @Override
  protected void drawConstrainer(Graphics2D g) {
    // The super-implementation draws only for positive coordinates, which we don't want.
    getConstrainer().draw(g, this);
  }

  /**
   * Draws a focus circle around the currently selected figure.
   *
   * @param g2d
   */
  protected void highlightFocus(Graphics2D g2d) {
    if (fFocusFigure == null || !fFocusFigure.isVisible()) {
      return;
    }

    final Figure currentFocusFigure = fFocusFigure;
    Rectangle2D.Double bounds = fFocusFigure.getBounds();
    double xCenter = bounds.getCenterX();
    double yCenter = bounds.getCenterY();

    if (fFocusFigure instanceof PathConnection) {
      xCenter = ((PathConnection) fFocusFigure).getCenter().x;
      yCenter = ((PathConnection) fFocusFigure).getCenter().y;
    }

    Point2D.Double pCenterView = new Point2D.Double(xCenter, yCenter);
    Point pCenterDrawing = drawingToView(pCenterView);

    // Create a radial gradient, transparent in the middle.
    Point2D center
        = new Point2D.Float((float) pCenterDrawing.x, (float) pCenterDrawing.y);
    float radius = 30;
    float[] dist = {0.0f, 0.7f, 0.8f, 1.0f};
    Color[] colors = {
      new Color(1.0f, 1.0f, 1.0f, 0.0f), // Focus: 100% transparent
      new Color(1.0f, 1.0f, 1.0f, 0.0f),
      new Color(1.0f, 0.0f, 0.0f, 0.7f), // Circle: red
      new Color(0.9f, 0.9f, 0.9f, 0.5f) // Background
    };
    RadialGradientPaint p
        = new RadialGradientPaint(center, radius, dist, colors,
                                  MultipleGradientPaint.CycleMethod.NO_CYCLE);

    Graphics2D gFocus = (Graphics2D) g2d.create();
    gFocus.setPaint(p);
    gFocus.fillRect(0, 0, getWidth(), getHeight());
    gFocus.dispose();

    // After drawing the RadialGradientPaint the drawing area needs to be
    // repainted, otherwise the GradientPaint isn't drawn correctly or
    // the old one isn't removed. We make sure the repaint() call doesn't
    // end in an infinite loop.
    loopProofRepaintDrawingArea();

    // after 3 seconds the RadialGradientPaint is removed
    new Thread(() -> {
      try {
        synchronized (AbstractOpenTCSDrawingView.this) {
          AbstractOpenTCSDrawingView.this.wait(3000);
        }
      }
      catch (InterruptedException ex) {
      }

      // prevents repainting of the drawing area if in the 3 second wait
      // time another figure was selected
      if (fFocusFigure == currentFocusFigure) {
        fFocusFigure = null;
        repaint();
      }
    }).start();
  }

  protected void loopProofRepaintDrawingArea() {
    if (doRepaint) {
      repaintDrawingArea();
      doRepaint = false;
    }
    else {
      doRepaint = true;
    }
  }

  protected ModelManager getModelManager() {
    return modelManager;
  }

  /**
   * The detailLevel indicates what type of Handles are supposed to be shouwn. In Operating mode,
   * we require the type of handles for our figures that do not allow moving, that is
   * indicated by -1.
   * In modelling mode we require the regular Handles, indicated by 0.
   */
  private void refreshDetailLevel() {
    if (OperationMode.OPERATING.equals(appState.getOperationMode())) {
      setHandleDetailLevel(-1);
    }
    else {
      setHandleDetailLevel(0);
    }
  }

  /**
   * Enables the listener for updating the offset figures.
   */
  private void addOffsetListener(OpenTCSDrawingEditor newEditor) {
    offsetListener = new OffsetListener(newEditor);
    addComponentListener(offsetListener);
  }

  /**
   * Computes the rectangle to draw for scrolling to the given figure.
   *
   * @param figure The figure to be shown.
   * @return The rectangle area to be drawn.
   */
  private Rectangle computeVisibleRectangleForFigure(Figure figure) {
    // The rectangle that encloses the figure
    Rectangle2D.Double bounds = computeBounds(figure);

    final int margin = 50;

    Point pCenterDrawing = drawingToView(new Point2D.Double(bounds.getCenterX() - margin,
                                                            bounds.getCenterY() - margin));
    Dimension dBounds = new Dimension((int) (bounds.getWidth() + 2 * margin),
                                      (int) (bounds.getHeight() + 2 * margin));

    return new Rectangle(pCenterDrawing, dBounds);
  }

  /**
   * Computes the rectangle enclosing the given figure.
   *
   * @param figure The figure.
   * @return The rectangle enclosing the given figure.
   */
  protected Rectangle2D.Double computeBounds(Figure figure) {
    // The rectangle that encloses the figure
    Rectangle2D.Double bounds = figure.getBounds();

    if (figure instanceof LabeledFigure) {
      // Also show the label
      LabeledFigure lf = (LabeledFigure) figure;
      TCSLabelFigure label = lf.getLabel();

      if (label != null) {
        Rectangle2D.Double labelBounds = label.getBounds();
        bounds.add(labelBounds);
      }
    }

    return bounds;
  }

  /**
   * Computes a fitting zoom level for displaying all figures currently in the drawing.
   *
   * @param drawing The drawing.
   * @return The zoom level.
   */
  private double computeZoomLevelToDisplayAllFigures(Drawing drawing) {
    // Rectangle that contains all figures
    Rectangle2D.Double drawingArea = drawing.getDrawingArea();
    double wDrawing = drawingArea.width + 2 * 20;
    double hDrawing = drawingArea.height + 2 * 20;
    // The currently visible rectangle
    Rectangle visibleRect = getComponent().getVisibleRect();

    double xFactor = visibleRect.width / wDrawing;
    double yFactor = visibleRect.height / hDrawing;

    // Find the smallest, and limit to 400%.
    double newZoom = Math.min(Math.min(xFactor, yFactor), 4.0);

    return roundToTwoDecimalPlaces(newZoom);
  }

  /**
   * Rounds the given value so that its decimal representation has only two places.
   *
   * @param value The value.
   * @return The rounded value.
   */
  private double roundToTwoDecimalPlaces(double value) {
    DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
    symbols.setDecimalSeparator('.');
    DecimalFormat twoDForm = new DecimalFormat("#.##", symbols);
    return Double.parseDouble(twoDForm.format(value));
  }

  public abstract class AbstractExtendedEventHandler
      extends DefaultDrawingView.EventHandler {

    @Override // CompositeFigureListener
    public void figureRemoved(CompositeFigureEvent evt) {
      if (evt.getChildFigure() instanceof BitmapFigure) {
        BitmapFigure bmFigure = (BitmapFigure) evt.getChildFigure();

        if (!bmFigure.isTemporarilyRemoved()) {
          BitmapFigure childFigure = (BitmapFigure) evt.getChildFigure();
          bitmapFigures.remove(childFigure);
        }
      }

      super.figureRemoved(evt);
    }

    @Override
    public void focusGained(FocusEvent e) {
      super.focusGained(e);

      if (getEditor() != null) {
        List<BitmapFigure> figuresToRemove = new ArrayList<>();

        for (Figure fig : getDrawing().getFiguresFrontToBack()) {
          if (fig instanceof BitmapFigure) {
            figuresToRemove.add((BitmapFigure) fig);
          }
          // Commented out on 2020-07-17 by <NAME>:
          // During the integration of layers this block caused some problems. When a layer is 
          // hidden, setVisible(false) is called for all figures contained in that particular layer.
          // This block caused all figures to be shown again once the drawing view gained focus.
          // The purpose of this block is not quite clear, but it seems a bit strange at least.
          //if (shouldShowFigure(fig)) {
          //  ((AbstractFigure) fig).setVisible(true);
          //}
        }

        for (BitmapFigure figure : figuresToRemove) {
          figure.setTemporarilyRemoved(true);
          getDrawing().remove(figure);
        }

        for (BitmapFigure bmFigure : bitmapFigures) {
          bmFigure.setTemporarilyRemoved(false);
          getDrawing().add(bmFigure);
          getDrawing().sendToBack(bmFigure);
        }
      }
    }

    @Override // FigureListener
    public void figureRequestRemove(FigureEvent evt) {
      super.figureRequestRemove(evt);

      if (evt.getFigure() instanceof BitmapFigure) {
        BitmapFigure bmFigure = (BitmapFigure) evt.getFigure();

        if (!bmFigure.isTemporarilyRemoved()) {
          BitmapFigure figure = (BitmapFigure) evt.getFigure();
          bitmapFigures.remove(figure);
        }
      }
    }

    protected abstract boolean shouldShowFigure(Figure figure);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/priorization/candidate/CandidateComparatorByCompleteRoutingCosts.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.priorization.candidate;

import java.util.Comparator;
import org.opentcs.strategies.basic.dispatching.AssignmentCandidate;

/**
 * Compares {@link AssignmentCandidate}s by routing costs.
 * Note: this comparator imposes orderings that are inconsistent with equals.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class CandidateComparatorByCompleteRoutingCosts
    implements Comparator<AssignmentCandidate> {

  /**
   * A key used for selecting this comparator in a configuration setting.
   * Should be unique among all keys.
   */
  public static final String CONFIGURATION_KEY = "BY_COMPLETE_ROUTING_COSTS";

  /**
   * Compares two candidates by their routing costs.
   * Note: this comparator imposes orderings that are inconsistent with equals.
   *
   * @see Comparator#compare(java.lang.Object, java.lang.Object)
   * @param candidate1 The first candidate
   * @param candidate2 The second candidate
   * @return the value 0 if candidate1 and candidate2 have the same routing costs;
   * a value less than 0 if candidate1 has a lower routing cost than candidate2;
   * and a value greater than 0 otherwise.
   */
  @Override
  public int compare(AssignmentCandidate candidate1, AssignmentCandidate candidate2) {
    // Lower routing costs are better.
    return Long.compare(candidate1.getCompleteRoutingCosts(), candidate2.getCompleteRoutingCosts());
  }

}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/dockable/AbstractDockingManager.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.dockable;

import bibliothek.gui.dock.common.CContentArea;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CVetoClosingEvent;
import bibliothek.gui.dock.common.event.CVetoClosingListener;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
import javax.swing.JComponent;

/**
 * Utility class for working with dockables.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public abstract class AbstractDockingManager
    implements DockingManager {

  /**
   * PropertyChangeEvent when a floating dockable closes.
   */
  public static final String DOCKABLE_CLOSED = "DOCKABLE_CLOSED";
  /**
   * Map that contains all tab panes. They are stored by their id.
   */
  private final Map<String, CStack> tabPanes = new HashMap<>();
  /**
   * Control for the dockable panels.
   */
  private final CControl control;
  /**
   * The listeners for closing events.
   */
  private final List<PropertyChangeListener> listeners = new ArrayList<>();

  public AbstractDockingManager(CControl control) {
    this.control = requireNonNull(control, "control");
  }

  @Override
  public void addPropertyChangeListener(PropertyChangeListener listener) {
    if (!listeners.contains(listener)) {
      listeners.add(listener);
    }
  }

  /**
   * Creates a new dockable.
   *
   * @param id The unique id for this dockable.
   * @param title The title text of this new dockable.
   * @param comp The JComponent wrapped by the new dockable.
   * @param closeable If the dockable can be closeable or not.
   * @return The newly created dockable.
   */
  public DefaultSingleCDockable createDockable(String id,
                                               String title,
                                               JComponent comp,
                                               boolean closeable) {
    Objects.requireNonNull(id, "id is null");
    Objects.requireNonNull(title, "title is null");
    Objects.requireNonNull(comp, "comp is null");
    if (control == null) {
      return null;
    }
    DefaultSingleCDockable dockable = new DefaultSingleCDockable(id, title);
    dockable.setCloseable(closeable);
    dockable.add(comp);
    return dockable;
  }

  /**
   * Creates a new floating dockable.
   *
   * @param id The unique id for this dockable.
   * @param title The title text of this new dockable.
   * @param comp The JComponent wrapped by the new dockable.
   * @return The newly created dockable.
   */
  public DefaultSingleCDockable createFloatingDockable(String id,
                                                       String title,
                                                       JComponent comp) {
    if (control == null) {
      return null;
    }
    final DefaultSingleCDockable dockable = new DefaultSingleCDockable(id, title);
    dockable.setCloseable(true);
    dockable.setFocusComponent(comp);
    dockable.add(comp);
    dockable.addVetoClosingListener(new CVetoClosingListener() {

      @Override
      public void closing(CVetoClosingEvent event) {
      }

      @Override
      public void closed(CVetoClosingEvent event) {
        fireFloatingDockableClosed(dockable);
      }
    });
    control.addDockable(dockable);
    dockable.setExtendedMode(ExtendedMode.EXTERNALIZED);
    Rectangle centerRectangle = control.getContentArea().getCenter().getBounds();
    dockable.setLocation(CLocation.external((centerRectangle.width - comp.getWidth()) / 2,
                                            (centerRectangle.height - comp.getHeight()) / 2,
                                            comp.getWidth(),
                                            comp.getHeight()));
    return dockable;
  }

  /**
   * Adds a dockable as tab to the tab pane identified by the given id.
   *
   * @param newTab The new dockable that shall be added.
   * @param id The ID of the tab pane.
   * @param index Index where to insert the dockable in the tab pane.
   */
  public void addTabTo(DefaultSingleCDockable newTab, String id, int index) {
    Objects.requireNonNull(newTab, "newTab is null.");
    Objects.requireNonNull(id, "id is null");
    CStack tabPane = tabPanes.get(id);
    if (tabPane != null) {
      control.addDockable(newTab);
      newTab.setWorkingArea(tabPane);
      tabPane.getStation().add(newTab.intern(), index);
      tabPane.getStation().setFrontDockable(newTab.intern());
    }
  }

  @Override
  public void removeDockable(SingleCDockable dockable) {
    Objects.requireNonNull(dockable, "dockable is null");
    if (control != null) {
      control.removeDockable(dockable);
    }
  }

  @Override
  public void removeDockable(String id) {
    Objects.requireNonNull(id);
    SingleCDockable dock = control.getSingleDockable(id);
    if (dock != null) {
      removeDockable(dock);
    }
  }

  /**
   * Returns the CControl.
   *
   * @return The CControl.
   */
  public CControl getCControl() {
    return control;
  }

  /**
   * Returns the whole component with all dockables, tab panes etc.
   *
   * @return The CContentArea of the CControl.
   */
  public CContentArea getContentArea() {
    if (control != null) {
      return control.getContentArea();
    }
    else {
      return null;
    }
  }

  /**
   * Returns the tab pane with the given id.
   *
   * @param id ID of the tab pane.
   * @return The tab pane or null if there is no tab pane with this id.
   */
  public CStack getTabPane(String id) {
    if (control != null) {
      return tabPanes.get(id);
    }
    else {
      return null;
    }
  }

  public abstract void reset();

  /**
   * Wraps all given JComponents into a dockable and deploys them on the CControl.
   */
  public abstract void initializeDockables();

  protected void addTabPane(String id, CStack tabPane) {
    tabPanes.put(id, tabPane);
  }

  /**
   * Hides a dockable (by actually removing it from its station).
   *
   * @param station The CStackDockStation the dockable belongs to.
   * @param dockable The dockable to hide.
   */
  public void hideDockable(CStackDockStation station, DefaultSingleCDockable dockable) {
    int index = station.indexOf(dockable.intern());

    if (index <= -1) {
      station.add(dockable.intern(), station.getDockableCount());
      index = station.indexOf(dockable.intern());
    }
    station.remove(index);
  }

  /**
   * Shows a dockable (by actually adding it to its station).
   *
   * @param station The CStackDockStation the dockable belongs to.
   * @param dockable The dockable to show.
   * @param index Where to add the dockable.
   */
  public void showDockable(CStackDockStation station,
                           DefaultSingleCDockable dockable,
                           int index) {
    if (station.indexOf(dockable.intern()) <= -1) {
      station.add(dockable.intern(), index);
    }
  }

  /**
   * Sets the visibility status of a dockable with the given id.
   *
   * @param id The id of the dockable.
   * @param visible If it shall be visible or not.
   */
  public void setDockableVisibility(String id, boolean visible) {
    if (control != null) {
      SingleCDockable dockable = control.getSingleDockable(id);
      if (dockable != null) {
        dockable.setVisible(visible);
      }
    }
  }

  /**
   * Checks if the given dockable is docked to its CStackDockStation.
   *
   * @param station The station the dockable should be docked in.
   * @param dockable The dockable to check.
   * @return True if it is docked, false otherwise.
   */
  public boolean isDockableDocked(CStackDockStation station, DefaultSingleCDockable dockable) {
    return station.indexOf(dockable.intern()) <= -1;
  }

  /**
   * Fires a <code>PropertyChangeEvent</code> when a floatable dockable is closed
   * (eg a plugin panel).
   *
   * @param dockable The dockable that was closed.
   */
  private void fireFloatingDockableClosed(DefaultSingleCDockable dockable) {
    for (PropertyChangeListener listener : listeners) {
      listener.propertyChange(
          new PropertyChangeEvent(this, DOCKABLE_CLOSED, dockable, dockable));
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/event/DrawingEditorListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.event;

import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;

/**
 * An interface that has to be implemented by the application to receive
 * events from the <code>DrawingEditor</code>. Events are: figure added,
 * figure removed and figure selected.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 * @see DrawingEditorEvent
 */
public interface DrawingEditorListener {

  /**
   * Gets called when a figure is added in the {@link OpenTCSDrawingEditor}
   * by an action of the user.
   *
   * @param e Event for when a figure is added to the OpenTCSDrawingEditor.
   */
  void figureAdded(DrawingEditorEvent e);

  /**
   * Gets called when a figure is removed by the user in the
   * <code>OpenTCSDrawingEditor</code>.
   *
   * @param e The fired event.
   */
  void figureRemoved(DrawingEditorEvent e);

  /**
   * Gets called when a figure was selected in the {@link OpenTCSDrawingEditor}.
   *
   * @param e The fired event.
   */
  void figureSelected(DrawingEditorEvent e);
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/NullPeripheralCommAdapter.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import javax.annotation.Nonnull;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import org.opentcs.data.peripherals.PeripheralJob;
import org.opentcs.drivers.peripherals.PeripheralAdapterCommand;
import org.opentcs.drivers.peripherals.PeripheralCommAdapter;
import org.opentcs.drivers.peripherals.PeripheralJobCallback;
import org.opentcs.drivers.peripherals.PeripheralProcessModel;
import org.opentcs.util.ExplainedBoolean;

/**
 * A {@link PeripheralCommAdapter} implementation that is doing nothing.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullPeripheralCommAdapter
    implements PeripheralCommAdapter {

  /**
   * The process model.
   */
  private final PeripheralProcessModel processModel;

  /**
   * Creates a new instance.
   *
   * @param location The reference to the location this adapter is attached to.
   */
  public NullPeripheralCommAdapter(@Nonnull TCSResourceReference<Location> location) {
    this.processModel = new PeripheralProcessModel(location);
  }

  @Override
  public void initialize() {
  }

  @Override
  public boolean isInitialized() {
    return true;
  }

  @Override
  public void terminate() {
  }

  @Override
  public void enable() {
  }

  @Override
  public void disable() {
  }

  @Override
  public boolean isEnabled() {
    return false;
  }

  @Override
  public PeripheralProcessModel getProcessModel() {
    return processModel;
  }

  @Override
  public ExplainedBoolean canProcess(PeripheralJob job) {
    return new ExplainedBoolean(false, "Can't process any jobs.");
  }

  @Override
  public void process(PeripheralJob job, PeripheralJobCallback callback) {
  }

  @Override
  public void execute(PeripheralAdapterCommand command) {
  }
}


<|start_filename|>openTCS-PlantOverview-Common/src/main/java/org/opentcs/guing/components/drawing/course/NormalCoordinateSystem.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.course;

import java.awt.Point;
import java.awt.geom.Point2D;

/**
 * A coordinate system strategy that converts pixel coordinates into real coordinates.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class NormalCoordinateSystem
    implements CoordinateSystem {

  /**
   * Creates a new instance.
   */
  public NormalCoordinateSystem() {
  }

  @Override
  public Point2D toPixel(Point refPointLocation, Point2D realValue, double scaleX, double scaleY) {
    double xPixel = realValue.getX() / scaleX;
    double yPixel = realValue.getY() / scaleY;
    return new Point2D.Double(refPointLocation.x + xPixel, -(refPointLocation.y + yPixel));
  }

  @Override
  public Point2D toReal(Point refPointLocation, Point pixelValue, double scaleX, double scaleY) {
    int xDiff = pixelValue.x - refPointLocation.x;
    int yDiff = pixelValue.y - refPointLocation.y;
    return new Point2D.Double(scaleX * xDiff, -scaleY * yDiff);
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/application/action/course/FollowVehicleAction.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.action.course;

import com.google.inject.assistedinject.Assisted;
import java.awt.event.ActionEvent;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.AbstractAction;
import javax.swing.JCheckBoxMenuItem;
import org.opentcs.guing.components.drawing.OpenTCSDrawingEditor;
import org.opentcs.guing.components.drawing.OpenTCSDrawingView;
import org.opentcs.guing.model.elements.VehicleModel;
import static org.opentcs.guing.util.I18nPlantOverviewOperating.VEHICLEPOPUP_PATH;
import org.opentcs.thirdparty.jhotdraw.util.ResourceBundleUtil;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class FollowVehicleAction
    extends AbstractAction {

  /**
   * Automatically moves the drawing so a vehicle is always visible.
   */
  public static final String ID = "course.vehicle.follow";
  
  private static final ResourceBundleUtil BUNDLE = ResourceBundleUtil.getBundle(VEHICLEPOPUP_PATH);
  /**
   * The vehicle.
   */
  private final VehicleModel vehicleModel;
  /**
   * The drawing editor.
   */
  private final OpenTCSDrawingEditor drawingEditor;

  /**
   * Creates a new instance.
   *
   * @param vehicle The selected vehicle.
   * @param drawingEditor The application's drawing editor.
   */
  @Inject
  public FollowVehicleAction(@Assisted VehicleModel vehicle,
                             OpenTCSDrawingEditor drawingEditor) {
    this.vehicleModel = requireNonNull(vehicle, "vehicle");
    this.drawingEditor = requireNonNull(drawingEditor, "drawingEditor");
    
    putValue(NAME, BUNDLE.getString("followVehicleAction.name"));
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    JCheckBoxMenuItem checkBox = (JCheckBoxMenuItem) evt.getSource();
    OpenTCSDrawingView drawingView = drawingEditor.getActiveView();

    if (drawingView != null) {
      if (checkBox.isSelected()) {
        drawingView.followVehicle(vehicleModel);
      }
      else {
        drawingView.stopFollowVehicle();
      }
    }
  }

}


<|start_filename|>openTCS-API-Base/src/main/java/org/opentcs/access/to/model/PathCreationTO.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.access.to.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import org.opentcs.access.to.CreationTO;
import org.opentcs.access.to.peripherals.PeripheralOperationCreationTO;
import org.opentcs.data.model.Couple;
import org.opentcs.data.model.Path.Layout.ConnectionType;
import static org.opentcs.util.Assertions.checkArgument;

/**
 * A transfer object describing a path in the plant model.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PathCreationTO
    extends CreationTO
    implements Serializable {

  /**
   * The point name this path originates in.
   */
  @Nonnull
  private String srcPointName;
  /**
   * The point name this path ends in.
   */
  @Nonnull
  private String destPointName;
  /**
   * This path's length (in mm).
   */
  private long length = 1;
  /**
   * The absolute maximum allowed forward velocity on this path (in mm/s).
   * A value of 0 (default) means forward movement is not allowed on this path.
   */
  private int maxVelocity;
  /**
   * The absolute maximum allowed reverse velocity on this path (in mm/s).
   * A value of 0 (default) means reverse movement is not allowed on this path.
   */
  private int maxReverseVelocity;
  /**
   * The peripheral operations to be performed when a vehicle travels along this path.
   */
  private List<PeripheralOperationCreationTO> peripheralOperations;
  /**
   * A flag for marking this path as locked (i.e. to prevent vehicles from using it).
   */
  private boolean locked;
  /**
   * The information regarding the grahical representation of this path.
   */
  private Layout layout = new Layout();

  /**
   * Creates a new instance.
   *
   * @param name The name of this path.
   * @param srcPointName The point name this path originates in.
   * @param destPointName The point name this path ends in.
   */
  public PathCreationTO(@Nonnull String name,
                        @Nonnull String srcPointName,
                        @Nonnull String destPointName) {
    super(name);
    this.srcPointName = requireNonNull(srcPointName, "srcPointName");
    this.destPointName = requireNonNull(destPointName, "destPointName");
    this.peripheralOperations = new ArrayList<>();
  }

  private PathCreationTO(String name,
                         @Nonnull String srcPointName,
                         @Nonnull String destPointName,
                         @Nonnull Map<String, String> properties,
                         long length,
                         int maxVelocity,
                         int maxReverseVelocity,
                         List<PeripheralOperationCreationTO> peripheralOperations,
                         boolean locked,
                         @Nonnull Layout layout) {
    super(name, properties);
    this.srcPointName = requireNonNull(srcPointName, "srcPointName");
    this.destPointName = requireNonNull(destPointName, "destPointName");
    this.length = length;
    this.maxVelocity = maxVelocity;
    this.maxReverseVelocity = maxReverseVelocity;
    this.peripheralOperations = new ArrayList<>(requireNonNull(peripheralOperations,
                                                               "peripheralOperations"));
    this.locked = locked;
    this.layout = requireNonNull(layout, "layout");
  }

  /**
   * Creates a copy of this object with the given name.
   *
   * @param name The new name.
   * @return A copy of this object, differing in the given name.
   */
  @Override
  public PathCreationTO withName(@Nonnull String name) {
    return new PathCreationTO(name,
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the point name this path originates in.
   *
   * @return The point name this path originates in.
   */
  @Nonnull
  public String getSrcPointName() {
    return srcPointName;
  }

  /**
   * Creates a copy of this object with the given point name this path originates in.
   *
   * @param srcPointName The new source point name.
   * @return A copy of this object, differing in the given source point.
   */
  public PathCreationTO withSrcPointName(@Nonnull String srcPointName) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the point name this path ends in.
   *
   * @return The point name this path ends in.
   */
  @Nonnull
  public String getDestPointName() {
    return destPointName;
  }

  /**
   * Creates a copy of this object with the given destination point.
   *
   * @param destPointName The new source point.
   * @return A copy of this object, differing in the given value.
   */
  public PathCreationTO withDestPointName(@Nonnull String destPointName) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the length of this path (in mm).
   *
   * @return The length of this path (in mm).
   */
  public long getLength() {
    return length;
  }

  /**
   * Creates a copy of this object with the given path length (in mm).
   *
   * @param length the new length (in mm). Must be a positive value.
   * @return A copy of this object, differing in the given length.
   */
  public PathCreationTO withLength(long length) {
    checkArgument(length > 0, "length must be a positive value: " + length);
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the maximum allowed forward velocity (in mm/s) for this path.
   *
   * @return The maximum allowed forward velocity (in mm/s). A value of 0 means forward movement is
   * not allowed on this path.
   */
  public int getMaxVelocity() {
    return maxVelocity;
  }

  /**
   * Creates a copy of this object with the maximum allowed forward velocity (in mm/s) for this path.
   *
   * @param maxVelocity The new maximum allowed velocity (in mm/s). May not be a negative value.
   * @return A copy of this object, differing in the given maximum velocity.
   */
  public PathCreationTO withMaxVelocity(int maxVelocity) {
    checkArgument(maxVelocity >= 0,
                  "maxVelocity may not be a negative value: " + maxVelocity);
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the maximum allowed reverse velocity (in mm/s) for this path.
   *
   * @return The maximum allowed reverse velocity (in mm/s). A value of 0 means reverse movement is
   * not allowed on this path.
   */
  public int getMaxReverseVelocity() {
    return maxReverseVelocity;
  }

  /**
   * Creates a copy of this object with the allowed maximum reverse velocity (in mm/s).
   *
   * @param maxReverseVelocity The new maximum allowed reverse velocity (in mm/s). Must not be a
   * negative value.
   * @return A copy of this object, differing in the given maximum reverse velocity.
   */
  public PathCreationTO withMaxReverseVelocity(int maxReverseVelocity) {
    checkArgument(maxReverseVelocity >= 0,
                  "maxReverseVelocity may not be a negative value: " + maxReverseVelocity);
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the peripheral operations to be performed when a vehicle travels along this path.
   *
   * @return The peripheral operations to be performed when a vehicle travels along this path.
   */
  public List<PeripheralOperationCreationTO> getPeripheralOperations() {
    return Collections.unmodifiableList(peripheralOperations);
  }

  /**
   * Creates a copy of this object with the given peripheral operations.
   *
   * @param peripheralOperations The peripheral operations.
   * @return A copy of this object, differing in the given peripheral operations.
   */
  public PathCreationTO withPeripheralOperations(
      @Nonnull List<PeripheralOperationCreationTO> peripheralOperations) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the lock status of this path (i.e. whether this path my be used by vehicles or not).
   *
   * @return {@code true} if this path is currently locked (i.e. it may not be used by vehicles),
   * else {@code false}.
   */
  public boolean isLocked() {
    return locked;
  }

  /**
   * Creates a copy of this object that is locked if {@code locked==true} and unlocked otherwise.
   *
   * @param locked If {@code true}, this path will be locked when the method call returns; if
   * {@code false}, this path will be unlocked.
   * @return a copy of this object, differing in the locked attribute.
   */
  public PathCreationTO withLocked(boolean locked) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Creates a copy of this object with the given properties.
   *
   * @param properties The new properties.
   * @return A copy of this object, differing in the given properties.
   */
  @Override
  public PathCreationTO withProperties(@Nonnull Map<String, String> properties) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              properties,
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Creates a copy of this object and adds the given property.
   * If value == null, then the key-value pair is removed from the properties.
   *
   * @param key the key.
   * @param value the value
   * @return A copy of this object that either
   * includes the given entry in it's current properties, if value != null or
   * excludes the entry otherwise.
   */
  @Override
  public PathCreationTO withProperty(@Nonnull String key, @Nonnull String value) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              propertiesWith(key, value),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  /**
   * Returns the information regarding the grahical representation of this path.
   *
   * @return The information regarding the grahical representation of this path.
   */
  public Layout getLayout() {
    return layout;
  }

  /**
   * Creates a copy of this object, with the given layout.
   *
   * @param layout The value to be set in the copy.
   * @return A copy of this object, differing in the given value.
   */
  public PathCreationTO withLayout(Layout layout) {
    return new PathCreationTO(getName(),
                              srcPointName,
                              destPointName,
                              getModifiableProperties(),
                              length,
                              maxVelocity,
                              maxReverseVelocity,
                              peripheralOperations,
                              locked,
                              layout);
  }

  @Override
  public String toString() {
    return "PathCreationTO{"
        + "name=" + getName()
        + ", srcPointName=" + srcPointName
        + ", destPointName=" + destPointName
        + ", length=" + length
        + ", maxVelocity=" + maxVelocity
        + ", maxReverseVelocity=" + maxReverseVelocity
        + ", peripheralOperations=" + peripheralOperations
        + ", locked=" + locked
        + ", layout=" + layout
        + ", properties=" + getProperties()
        + '}';
  }

  /**
   * Contains information regarding the grahical representation of a path.
   */
  public static class Layout
      implements Serializable {

    /**
     * The connection type the path is represented as.
     */
    private final ConnectionType connectionType;
    /**
     * Control points describing the way the path is drawn (if the connection type
     * is {@link ConnectionType#BEZIER}, {@link ConnectionType#BEZIER_3}
     * or {@link ConnectionType#POLYPATH}).
     */
    private final List<Couple> controlPoints;
    /**
     * The ID of the layer on which the path is to be drawn.
     */
    private final int layerId;

    /**
     * Creates a new instance.
     */
    public Layout() {
      this(ConnectionType.DIRECT, new ArrayList<>(), 0);
    }

    /**
     * Creates a new instance.
     *
     * @param connectionType The connection type a path is represented as.
     * @param controlPoints Control points describing the way the path is drawn.
     * @param layerId The ID of the layer on which the path is to be drawn.
     */
    public Layout(ConnectionType connectionType, List<Couple> controlPoints, int layerId) {
      this.connectionType = connectionType;
      this.controlPoints = requireNonNull(controlPoints, "controlPoints");
      this.layerId = layerId;
    }

    /**
     * Returns the connection type the path is represented as.
     *
     * @return The connection type the path is represented as.
     */
    public ConnectionType getConnectionType() {
      return connectionType;
    }

    /**
     * Creates a copy of this object, with the given connection type.
     *
     * @param connectionType The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withConnectionType(ConnectionType connectionType) {
      return new Layout(connectionType, controlPoints, layerId);
    }

    /**
     * Returns the control points describing the way the path is drawn.
     * Returns an empty list if connection type is not {@link ConnectionType#BEZIER},
     * {@link ConnectionType#BEZIER_3} or {@link ConnectionType#POLYPATH}.
     *
     * @return The control points describing the way the path is drawn.
     */
    public List<Couple> getControlPoints() {
      return Collections.unmodifiableList(controlPoints);
    }

    /**
     * Creates a copy of this object, with the given control points.
     *
     * @param controlPoints The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withControlPoints(List<Couple> controlPoints) {
      return new Layout(connectionType, controlPoints, layerId);
    }

    /**
     * Returns the ID of the layer on which the path is to be drawn.
     *
     * @return The layer ID.
     */
    public int getLayerId() {
      return layerId;
    }

    /**
     * Creates a copy of this object, with the given layer ID.
     *
     * @param layerId The value to be set in the copy.
     * @return A copy of this object, differing in the given value.
     */
    public Layout withLayer(int layerId) {
      return new Layout(connectionType, controlPoints, layerId);
    }

    @Override
    public String toString() {
      return "Layout{"
          + "connectionType=" + connectionType
          + ", controlPoints=" + controlPoints
          + ", layerId=" + layerId
          + '}';
    }
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/routing/DefaultRoutingGroupMapper.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.routing;

import org.opentcs.components.kernel.Router;
import static org.opentcs.components.kernel.Router.PROPKEY_ROUTING_GROUP;
import org.opentcs.components.kernel.routing.GroupMapper;
import org.opentcs.data.model.Vehicle;

/**
 * Determines a vehicle's routing group by reading it's {@link Router#PROPKEY_ROUTING_GROUP}
 * property. Returns {@link #DEFAULT_ROUTING_GROUP} if the property does not exist or is invalid.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class DefaultRoutingGroupMapper
    implements GroupMapper {

  /**
   * The default value of a vehicle's routing group.
   */
  private static final String DEFAULT_ROUTING_GROUP = "";

  @Override
  public String apply(Vehicle vehicle) {
    String propVal = vehicle.getProperty(PROPKEY_ROUTING_GROUP);

    return propVal == null ? DEFAULT_ROUTING_GROUP : propVal;
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/components/drawing/BlockChangeHandler.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.jhotdraw.draw.AbstractFigure;
import org.jhotdraw.draw.Figure;
import org.opentcs.guing.event.BlockChangeEvent;
import org.opentcs.guing.event.BlockChangeListener;
import org.opentcs.guing.model.FigureDecorationDetails;
import org.opentcs.guing.model.ModelComponent;
import org.opentcs.guing.model.elements.BlockModel;
import org.opentcs.guing.persistence.ModelManager;
import org.opentcs.guing.util.ModelComponentUtil;

/**
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class BlockChangeHandler
    implements BlockChangeListener {

  /**
   * The members/elements of a block mapped to the block model.
   */
  private final Map<BlockModel, Set<FigureDecorationDetails>> blockElementsHistory
      = new HashMap<>();

  /**
   * The manager keeping/providing the currently loaded model.
   */
  private final ModelManager modelManager;

  /**
   * Creates a new instance.
   *
   * @param modelManager The model manager.
   */
  @Inject
  public BlockChangeHandler(ModelManager modelManager) {
    this.modelManager = requireNonNull(modelManager, "modelManager");
  }

  @Override // BlockChangeListener
  public void courseElementsChanged(BlockChangeEvent e) {
    BlockModel block = (BlockModel) e.getSource();

    // Let the block's elements know the block they are now part of.
    Set<FigureDecorationDetails> blockElements = block.getPropertyElements().getItems().stream()
        .map(elementName -> modelManager.getModel().getModelComponent(elementName))
        .filter(modelComponent -> modelComponent instanceof FigureDecorationDetails)
        .map(modelComponent -> (FigureDecorationDetails) modelComponent)
        .collect(Collectors.toSet());
    for (FigureDecorationDetails component : blockElements) {
      component.addBlockModel(block);
    }

    // The elements that are no longer part of the block should also know this.
    Set<FigureDecorationDetails> removedBlockElements = updateBlockElementHistory(block,
                                                                                  blockElements);
    for (FigureDecorationDetails component : removedBlockElements) {
      component.removeBlockModel(block);
      // Update the figure so that it no longer appears as being part of the block.
      Figure figure = modelManager.getModel().getFigure(((ModelComponent) component));
      ((AbstractFigure) figure).fireFigureChanged();
    }

    updateBlock(block);
  }

  @Override // BlockChangeListener
  public void colorChanged(BlockChangeEvent e) {
    updateBlock((BlockModel) e.getSource());
  }

  @Override // BlockChangeListener
  public void blockRemoved(BlockChangeEvent e) {
    BlockModel block = (BlockModel) e.getSource();

    // Let the block's elements know they are no longer part of the block.
    Set<FigureDecorationDetails> removedBlockElements
        = updateBlockElementHistory(block, new HashSet<>());
    for (FigureDecorationDetails component : removedBlockElements) {
      component.removeBlockModel(block);
    }

    block.removeBlockChangeListener(this);
    updateBlock(block);
  }

  /**
   * Remembers the given set of components as the new block elements for the given
   * block model and returns the set difference of the old and the new block elements
   * (e.g. the elements that are no longer part of the block).
   *
   * @param block The block model.
   * @param newBlockElements The new block elements.
   * @return The set difference of the old and the new block elements.
   */
  private Set<FigureDecorationDetails> updateBlockElementHistory(
      BlockModel block,
      Set<FigureDecorationDetails> newBlockElements) {
    Set<FigureDecorationDetails> oldBlockElements = getBlockElements(block);
    Set<FigureDecorationDetails> removedBlockElements = new HashSet<>(oldBlockElements);

    removedBlockElements.removeAll(newBlockElements);

    oldBlockElements.clear();
    oldBlockElements.addAll(newBlockElements);

    return removedBlockElements;
  }

  private Set<FigureDecorationDetails> getBlockElements(BlockModel block) {
    if (!blockElementsHistory.containsKey(block)) {
      blockElementsHistory.put(block, new HashSet<>());
    }

    return blockElementsHistory.get(block);
  }

  private void updateBlock(BlockModel block) {
    for (Figure figure : ModelComponentUtil.getChildFigures(block, modelManager.getModel())) {
      ((AbstractFigure) figure).fireFigureChanged();
    }
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/LocationTypeActionsProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import org.opentcs.guing.model.ModelComponent;

/**
 * A property for location actions.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class LocationTypeActionsProperty
    extends StringSetProperty {

  /**
   * Creates a new instance.
   *
   * @param model The model component this property belongs to.
   */
  public LocationTypeActionsProperty(ModelComponent model) {
    super(model);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/peripherals/PeripheralEntryPool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.peripherals;

import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import org.opentcs.components.Lifecycle;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.TCSResourceReference;
import static org.opentcs.util.Assertions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides a pool of {@link PeripheralEntry}s with an entry for every {@link Location} object in
 * the kernel.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralEntryPool
    implements Lifecycle {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralEntryPool.class);
  /**
   * The object service.
   */
  private final TCSObjectService objectService;
  /**
   * The entries of this pool.
   */
  private final Map<TCSResourceReference<Location>, PeripheralEntry> entries = new HashMap<>();
  /**
   * Whether the pool is initialized or not.
   */
  private boolean initialized;

  /**
   * Creates a new instance.
   *
   * @param objectService The object service.
   */
  @Inject
  public PeripheralEntryPool(@Nonnull TCSObjectService objectService) {
    this.objectService = requireNonNull(objectService, "objectService");
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    objectService.fetchObjects(Location.class).stream()
        .forEach(location -> entries.put(location.getReference(), new PeripheralEntry(location)));
    LOG.debug("Initialized peripheral entry pool: {}", entries);
    initialized = true;
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    entries.clear();
    initialized = false;
  }

  @Nonnull
  public Map<TCSResourceReference<Location>, PeripheralEntry> getEntries() {
    return entries;
  }

  /**
   * Returns the {@link PeripheralEntry} for the given location.
   *
   * @param location The reference to the location.
   * @return The entry for the given location.
   * @throws IllegalArgumentException If no entry is present for the given location.
   */
  @Nonnull
  public PeripheralEntry getEntryFor(@Nonnull TCSResourceReference<Location> location)
      throws IllegalArgumentException {
    requireNonNull(location, "location");
    checkArgument(entries.containsKey(location),
                  "No peripheral entry present for %s",
                  location.getName());
    return entries.get(location);
  }
}


<|start_filename|>openTCS-ModelEditor/src/main/java/org/opentcs/guing/application/toolbar/MultipleSelectionTool.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.application.toolbar;

import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import javax.swing.Action;
import javax.swing.JMenuItem;
import org.jhotdraw.draw.tool.DragTracker;
import org.jhotdraw.draw.tool.SelectAreaTracker;
import org.opentcs.guing.application.ApplicationState;
import org.opentcs.guing.application.menus.MenuFactory;
import org.opentcs.thirdparty.jhotdraw.application.toolbar.AbstractMultipleSelectionTool;

/**
 * The default selection tool.
 *
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 * @author <NAME> (Fraunhofer IML)
 */
public class MultipleSelectionTool
    extends AbstractMultipleSelectionTool {

  /**
   * A factory for menu items.
   */
  private final MenuFactory menuFactory;
  
  /**
   * Creates a new instance.
   *
   * @param appState Stores the application's current state.
   * @param menuFactory A factory for menu items in popup menus created by this tool.
   * @param selectAreaTracker The tracker to be used for area selections in the drawing.
   * @param dragTracker The tracker to be used for dragging figures.
   * @param drawingActions Drawing-related actions for the popup menus created by this tool.
   * @param selectionActions Selection-related actions for the popup menus created by this tool.
   */
  @Inject
  public MultipleSelectionTool(ApplicationState appState,
                               MenuFactory menuFactory,
                               SelectAreaTracker selectAreaTracker,
                               DragTracker dragTracker,
                               @Assisted("drawingActions") Collection<Action> drawingActions,
                               @Assisted("selectionActions") Collection<Action> selectionActions) {
    super(appState, selectAreaTracker, dragTracker, drawingActions, selectionActions);
    this.menuFactory = requireNonNull(menuFactory, "menuFactory");
  }

  @Override
  public List<JMenuItem> customPopupMenuItems() {
    // Points and Locations get two additional entries
    List<JMenuItem> actions = new ArrayList<>();
    actions.add(menuFactory.createModelToLayoutMenuItem(false));
    actions.add(menuFactory.createLayoutToModelMenuItem(false));
    return actions;
  }
}


<|start_filename|>openTCS-Strategies-Default/src/main/java/org/opentcs/strategies/basic/dispatching/phase/parking/ParkingPositionPriorityComparator.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.phase.parking;

import java.util.Comparator;
import static java.util.Objects.requireNonNull;
import javax.inject.Inject;
import org.opentcs.data.model.Point;

/**
 * Compares parking positions by their priorities.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ParkingPositionPriorityComparator
    implements Comparator<Point> {

  /**
   * A function computing the priority of a parking position.
   */
  private final ParkingPositionToPriorityFunction priorityFunction;

  /**
   * Creates a new instance.
   *
   * @param priorityFunction A function computing the priority of a parking position.
   */
  @Inject
  public ParkingPositionPriorityComparator(ParkingPositionToPriorityFunction priorityFunction) {
    this.priorityFunction = requireNonNull(priorityFunction, "priorityFunction");
  }

  @Override
  public int compare(Point point1, Point point2) {
    requireNonNull(point1, "point1");
    requireNonNull(point2, "point2");

    Integer point1Prio = priorityFunction.apply(point1);
    Integer point2Prio = priorityFunction.apply(point2);

    if (point1Prio != null && point2Prio == null) {
      return -1;
    }
    else if (point1Prio == null && point2Prio != null) {
      return 1;
    }
    else if (point1Prio == null && point2Prio == null) {
      return point1.getName().compareTo(point2.getName());
    }
    return point1Prio.compareTo(point2Prio);
  }
}


<|start_filename|>openTCS-Strategies-Default/src/test/java/org/opentcs/strategies/basic/dispatching/selection/orders/ContainsLockedTargetLocationsTest.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.strategies.basic.dispatching.selection.orders;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.*;
import static org.junit.Assert.*;
import org.mockito.ArgumentMatchers;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.opentcs.components.kernel.services.TCSObjectService;
import org.opentcs.data.TCSObject;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Location;
import org.opentcs.data.model.LocationType;
import org.opentcs.data.model.Point;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;

/**
 * Defines test cases for {@link ContainsLockedTargetLocations}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ContainsLockedTargetLocationsTest {

  /**
   * The class to test.
   */
  private ContainsLockedTargetLocations filter;
  /**
   * The object service to use.
   */
  private TCSObjectService objectService;
  /**
   * The local object pool to be used by the object service.
   */
  private Map<TCSObjectReference<?>, TCSObject<?>> localObjectPool;

  @Before
  public void setUp() {
    localObjectPool = new HashMap<>();
    objectService = mock(TCSObjectService.class);
    when(objectService.fetchObject(any(), ArgumentMatchers.<TCSObjectReference<?>>any()))
        .thenAnswer(invocation -> localObjectPool.get((TCSObjectReference<?>) invocation.getArgument(1)));
    filter = new ContainsLockedTargetLocations(objectService);
  }

  @Test
  public void shouldFilterTransportOrderWithLockedLocation() {
    Collection<String> result = filter.apply(transportOrderWithLockedLocation());
    assertFalse(result.isEmpty());
  }

  @Test
  public void shouldIgnoreTransportOrderWithUnlockedLocation() {
    Collection<String> result = filter.apply(transportOrderWithoutLockedLocation());
    assertTrue(result.isEmpty());
  }

  @Test
  public void shouldIgnoreTransportOrderWithPointDestination() {
    Collection<String> result = filter.apply(transportOrderWithPointDestination());
    assertTrue(result.isEmpty());
  }

  private TransportOrder transportOrderWithLockedLocation() {
    List<DriveOrder> driveOrders = new ArrayList<>();
    LocationType locationType = new LocationType("LocationType-1");

    Location location = new Location("Location-1", locationType.getReference());
    localObjectPool.put(location.getReference(), location);
    DriveOrder.Destination destination = new DriveOrder.Destination(location.getReference());
    driveOrders.add(new DriveOrder(destination));

    location = new Location("Location-2", locationType.getReference()).withLocked(true);
    localObjectPool.put(location.getReference(), location);
    destination = new DriveOrder.Destination(location.getReference());
    driveOrders.add(new DriveOrder(destination));

    return new TransportOrder("TransportOrder-1", driveOrders);
  }

  private TransportOrder transportOrderWithoutLockedLocation() {
    List<DriveOrder> driveOrders = new ArrayList<>();
    LocationType locationType = new LocationType("LocationType-1");

    Location location = new Location("Location-1", locationType.getReference());
    localObjectPool.put(location.getReference(), location);
    DriveOrder.Destination destination = new DriveOrder.Destination(location.getReference());
    driveOrders.add(new DriveOrder(destination));

    location = new Location("Location-2", locationType.getReference());
    localObjectPool.put(location.getReference(), location);
    destination = new DriveOrder.Destination(location.getReference());
    driveOrders.add(new DriveOrder(destination));

    return new TransportOrder("TransportOrder-1", driveOrders);
  }

  private TransportOrder transportOrderWithPointDestination() {
    List<DriveOrder> driveOrders = new ArrayList<>();

    Point point = new Point("Point-1");
    localObjectPool.put(point.getReference(), point);
    DriveOrder.Destination destination = new DriveOrder.Destination(point.getReference());
    driveOrders.add(new DriveOrder(destination));

    return new TransportOrder("TransportOrder-1", driveOrders);
  }
}


<|start_filename|>openTCS-Kernel/src/main/java/org/opentcs/kernel/vehicles/NullVehicleController.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernel.vehicles;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static java.util.Objects.requireNonNull;
import java.util.Queue;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opentcs.data.model.TCSResource;
import org.opentcs.data.order.DriveOrder;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.AdapterCommand;
import org.opentcs.drivers.vehicle.MovementCommand;
import org.opentcs.drivers.vehicle.VehicleController;
import org.opentcs.util.ExplainedBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Null-object implementation of {@link VehicleController}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class NullVehicleController
    implements VehicleController {

  /**
   * This class's Logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(NullVehicleController.class);
  /**
   * The associated vehicle's name.
   */
  private final String vehicleName;

  /**
   * Creates a new instance.
   *
   * @param vehicleName The associated vehicle's name.
   */
  public NullVehicleController(@Nonnull String vehicleName) {
    this.vehicleName = requireNonNull(vehicleName, "vehicleName");
  }

  @Override
  public void initialize() {
  }

  @Override
  public boolean isInitialized() {
    return true;
  }

  @Override
  public void terminate() {
  }

  @Override
  public void setTransportOrder(TransportOrder newOrder) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  @Deprecated
  public void setDriveOrder(DriveOrder newOrder, Map<String, String> orderProperties) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  @Deprecated
  public void updateDriveOrder(DriveOrder newOrder, Map<String, String> orderProperties) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  public void abortTransportOrder(boolean immediate) {
    if (immediate) {
      clearDriveOrder();
    }
    else {
      abortDriveOrder();
    }
  }

  @Override
  @Deprecated
  public void clearDriveOrder() {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  @Deprecated
  public void abortDriveOrder() {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  @Deprecated
  public void clearCommandQueue() {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  public ExplainedBoolean canProcess(TransportOrder order) {
    return new ExplainedBoolean(false, "NullVehicleController");
  }

  @Override
  @Deprecated
  public ExplainedBoolean canProcess(List<String> operations) {
    return new ExplainedBoolean(false, "NullVehicleController");
  }

  @Override
  public void sendCommAdapterMessage(Object message) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  public void sendCommAdapterCommand(AdapterCommand command) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  public String getId() {
    return vehicleName;
  }

  @Override
  public boolean allocationSuccessful(Set<TCSResource<?>> resources) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
    return false;
  }

  @Override
  public void allocationFailed(Set<TCSResource<?>> resources) {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
  }

  @Override
  public Queue<MovementCommand> getCommandsSent() {
    LOG.warn("No comm adapter attached to vehicle {}", vehicleName);
    return new LinkedList<>();
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/components/drawing/figures/VehicleLabelFigure.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.drawing.figures;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import org.jhotdraw.draw.event.FigureEvent;
import org.opentcs.guing.model.elements.VehicleModel;

/**
 *
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class VehicleLabelFigure
    extends TCSLabelFigure {

  private static final Color COLOR_BACKGROUND = new Color(0xFFFFF0);  // beige
  private static final int MARGIN = 4;

  public VehicleLabelFigure(String vehicleName) {
    super(vehicleName);
  }

  @Override
  protected void drawFill(Graphics2D g) {
    if (getText() != null) {
      TextLayout layout = getTextLayout();
      Rectangle2D bounds = layout.getBounds();
      RoundRectangle2D.Double rr = new RoundRectangle2D.Double(
          bounds.getX() + origin.x - MARGIN,
          bounds.getY() + origin.y + layout.getAscent() - MARGIN,
          bounds.getWidth() + 2 * MARGIN,
          bounds.getHeight() + 2 + MARGIN,
          MARGIN, MARGIN);
      g.setPaint(COLOR_BACKGROUND);
      g.fill(rr);
    }
  }

  @Override
  protected void drawStroke(Graphics2D g) {
  }

  @Override
  protected void drawText(Graphics2D g) {
    if (getText() != null || isEditable()) {
      TextLayout layout = getTextLayout();
      g.setPaint(Color.BLUE.darker());
      layout.draw(g, (float) origin.x, (float) (origin.y + layout.getAscent()));
    }
  }

  @Override
  public void figureChanged(FigureEvent event) {
    if (event.getFigure() instanceof LabeledFigure) {
      LabeledFigure lf = (LabeledFigure) event.getFigure();
      TCSFigure figure = lf.getPresentationFigure();
      VehicleModel model = (VehicleModel) figure.getModel();
      String name = model.getName();

      if (model.getPoint() != null) {
        name += "@" + model.getPoint().getName();
      }

      setText(name);
      invalidate();
      validate();
    }
  }
}


<|start_filename|>openTCS-Common/src/main/java/org/opentcs/util/persistence/ModelParser.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.util.persistence;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import org.opentcs.access.to.model.PlantModelCreationTO;
import org.opentcs.util.persistence.v004.V004ModelParser;
import org.opentcs.util.persistence.v004.V004PlantModelTO;
import org.opentcs.util.persistence.v004.V004TOMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides methods for parsing {@link PlantModelCreationTO}s from/to a file.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class ModelParser {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(ModelParser.class);
  /**
   * The charset to use for the reader/writer.
   */
  private static final Charset CHARSET = Charset.forName("UTF-8");

  /**
   * Reads a model from the given file and parses it to a {@link PlantModelCreationTO} instance.
   *
   * @param file The model file to read.
   * @return The parsed {@link PlantModelCreationTO}.
   * @throws IOException If there was an error reading the model file.
   * @throws IllegalArgumentException If there is no parser for the version of the model file.
   */
  public PlantModelCreationTO readModel(File file)
      throws IOException {
    String modelVersion = peekModelVersion(file);

    LOG.debug("File '{}' contains a model version '{}'.", file.getAbsolutePath(), modelVersion);

    try (Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),
                                                                  CHARSET))) {
      return new V004ModelParser().read(reader, modelVersion);
    }
  }

  /**
   * Writes the given {@link PlantModelCreationTO} to the given file.
   *
   * @param model The model.
   * @param file The file to write the model to.
   * @throws IOException If there was an error writing to the model file.
   */
  public void writeModel(PlantModelCreationTO model, File file)
      throws IOException {
    try (Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),
                                                                   CHARSET))) {
      V004TOMapper mapper = new V004TOMapper();
      V004PlantModelTO mappedModel = mapper.map(model);
      mappedModel.toXml(writer);
    }
  }

  private String peekModelVersion(File file)
      throws IOException {
    try (Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),
                                                                  CHARSET))) {
      return ProbePlantModelTO.fromXml(reader).getVersion();
    }
  }
}


<|start_filename|>openTCS-OperationsDesk/src/main/java/org/opentcs/guing/transport/OrdersTable.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.transport;

import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

/**
 * A table for transport orders.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class OrdersTable
    extends JTable {

  /**
   * Creates a new instance of OrdersTable.
   *
   * @param tableModel das Tabellenmodell
   */
  public OrdersTable(TableModel tableModel) {
    super(tableModel);

    setRowSelectionAllowed(true);
    setFocusable(false);
  }

  @Override
  public boolean isCellEditable(int row, int column) {
    return false;
  }

  @Override
  public TableCellEditor getCellEditor(int row, int column) {
    TableModel tableModel = getModel();
    Object value = tableModel.getValueAt(row, column);
    TableCellEditor editor = getDefaultEditor(value.getClass());

    return editor;
  }

  @Override
  public TableCellRenderer getCellRenderer(int row, int column) {
    TableModel tableModel = getModel();
    Object value = tableModel.getValueAt(row, column);
    TableCellRenderer renderer = getDefaultRenderer(value.getClass());

    return renderer;
  }
}


<|start_filename|>openTCS-PlantOverview-Base/src/main/java/org/opentcs/guing/components/properties/type/StringSetProperty.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.guing.components.properties.type;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.opentcs.guing.model.ModelComponent;

/**
 * A property that contains a quantity of strings.
 *
 * @author <NAME> (ifak e.V. Magdeburg)
 */
public class StringSetProperty
    extends AbstractComplexProperty {

  /**
   * The strings.
   */
  private List<String> fItems = new LinkedList<>();

  /**
   * Creates a new instance.
   *
   * @param model The model component this property belongs to.
   */
  public StringSetProperty(ModelComponent model) {
    super(model);
  }

  @Override
  public Object getComparableValue() {
    StringBuilder sb = new StringBuilder();

    for (String s : fItems) {
      sb.append(s);
    }

    return sb.toString();
  }

  /**
   * Adds a string.
   *
   * @param item The string to add.
   */
  public void addItem(String item) {
    fItems.add(item);
  }

  /**
   * Sets the list of strings.
   *
   * @param items The list.
   */
  public void setItems(List<String> items) {
    fItems = items;
  }

  /**
   * Returns the list of string.
   *
   * @return The list.
   */
  public List<String> getItems() {
    return fItems;
  }

  @Override
  public void copyFrom(Property property) {
    StringSetProperty other = (StringSetProperty) property;
    List<String> items = new LinkedList<>(other.getItems());
    setItems(items);
  }

  @Override
  public String toString() {
    StringBuilder b = new StringBuilder();
    Iterator<String> e = getItems().iterator();

    while (e.hasNext()) {
      b.append(e.next());

      if (e.hasNext()) {
        b.append(", ");
      }
    }

    return b.toString();
  }

  @Override
  public Object clone() {
    StringSetProperty clone = (StringSetProperty) super.clone();
    List<String> items = new LinkedList<>(getItems());
    clone.setItems(items);

    return clone;
  }
}


<|start_filename|>openTCS-KernelControlCenter/src/main/java/org/opentcs/kernelcontrolcenter/peripherals/PeripheralsPanel.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.kernelcontrolcenter.peripherals;

import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.swing.RowFilter;
import javax.swing.table.TableRowSorter;
import org.opentcs.access.Kernel;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.common.peripherals.NullPeripheralCommAdapterDescription;
import org.opentcs.components.kernelcontrolcenter.ControlCenterPanel;
import org.opentcs.customizations.ServiceCallWrapper;
import org.opentcs.drivers.peripherals.PeripheralCommAdapterDescription;
import static org.opentcs.util.Assertions.checkState;
import org.opentcs.util.CallWrapper;
import org.opentcs.util.gui.StringTableCellRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A panel containing all locations representing peripheral devices.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public class PeripheralsPanel
    extends ControlCenterPanel {

  /**
   * This class's logger.
   */
  private static final Logger LOG = LoggerFactory.getLogger(PeripheralsPanel.class);
  /**
   * The service portal to use for kernel interaction.
   */
  private final KernelServicePortal servicePortal;
  /**
   * The call wrapper to use.
   */
  private final CallWrapper callWrapper;
  /**
   * The pool of peripheral devices.
   */
  private final LocalPeripheralEntryPool peripheralEntryPool;
  /**
   * The details panel.
   */
  private final PeripheralDetailPanel detailPanel;
  /**
   * The table row sorter to use.
   */
  private TableRowSorter<PeripheralTableModel> sorter;
  /**
   * Whether this component is initialized.
   */
  private boolean initialized;

  /**
   * Creates new instance.
   *
   * @param servicePortal The service portal to use for kernel interaction.
   * @param callWrapper The call wrapper to use for publishing events to the kernel.
   * @param peripheralEntryPool The pool of peripheral devices.
   * @param detailPanel The details panel.
   */
  @Inject
  public PeripheralsPanel(@Nonnull KernelServicePortal servicePortal,
                          @Nonnull @ServiceCallWrapper CallWrapper callWrapper,
                          @Nonnull LocalPeripheralEntryPool peripheralEntryPool,
                          @Nonnull PeripheralDetailPanel detailPanel) {
    this.servicePortal = requireNonNull(servicePortal, "servicePortal");
    this.callWrapper = requireNonNull(callWrapper, "callWrapper");
    this.peripheralEntryPool = requireNonNull(peripheralEntryPool, "peripheralEntryPool");
    this.detailPanel = requireNonNull(detailPanel, "detailPanel");

    initComponents();
    peripheralDetailsPanel.add(detailPanel);
  }

  @Override
  public boolean isInitialized() {
    return initialized;
  }

  @Override
  public void initialize() {
    if (isInitialized()) {
      return;
    }

    // Verify that the kernel is in a state in which controlling peripherals is possible.
    Kernel.State kernelState;
    try {
      kernelState = callWrapper.call(() -> servicePortal.getState());
    }
    catch (Exception ex) {
      LOG.warn("Error getting the kernel state", ex);
      return;
    }
    checkState(Kernel.State.OPERATING.equals(kernelState),
               "Cannot work in kernel state %s",
               kernelState);

    peripheralEntryPool.initialize();
    detailPanel.initialize();

    EventQueue.invokeLater(() -> {
      initPeripheralTable();
    });

    initialized = true;
  }

  @Override
  public void terminate() {
    if (!isInitialized()) {
      return;
    }

    detailPanel.terminate();
    peripheralEntryPool.terminate();

    initialized = false;
  }

  private void initPeripheralTable() {
    PeripheralTableModel model = new PeripheralTableModel(servicePortal, callWrapper);
    peripheralTable.setModel(model);
    peripheralTable.getColumnModel().getColumn(PeripheralTableModel.COLUMN_ADAPTER).setCellRenderer(
        new StringTableCellRenderer<PeripheralCommAdapterDescription>(
            description -> description.getDescription()
        )
    );
    sorter = new TableRowSorter<>(model);
    peripheralTable.setRowSorter(sorter);

    peripheralEntryPool.getEntries().forEach((location, entry) -> {
      model.addData(entry);
      entry.addPropertyChangeListener(model);
    });

    updateRowFilter();
  }

  private void updateRowFilter() {
    sorter.setRowFilter(RowFilter.andFilter(toRegexFilters()));
  }

  private List<RowFilter<PeripheralTableModel, Integer>> toRegexFilters() {
    List<RowFilter<PeripheralTableModel, Integer>> result = new ArrayList<>();
    result.add(RowFilter.regexFilter(".*", PeripheralTableModel.COLUMN_ADAPTER));
    if (hideDetachedLocationsCheckBox.isSelected()) {
      result.add(RowFilter.notFilter(
          RowFilter.regexFilter(NullPeripheralCommAdapterDescription.class.getSimpleName(),
                                PeripheralTableModel.COLUMN_ADAPTER))
      );
    }

    return result;
  }

  /**
   * This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    listPanel = new javax.swing.JPanel();
    filterPanel = new javax.swing.JPanel();
    hideDetachedLocationsCheckBox = new javax.swing.JCheckBox();
    jScrollPane1 = new javax.swing.JScrollPane();
    peripheralTable = new javax.swing.JTable();
    peripheralDetailsPanel = new javax.swing.JPanel();

    setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));

    listPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Peripheral devices in model"));
    listPanel.setMaximumSize(new java.awt.Dimension(464, 2147483647));
    listPanel.setMinimumSize(new java.awt.Dimension(464, 425));
    listPanel.setPreferredSize(new java.awt.Dimension(464, 424));
    listPanel.setLayout(new java.awt.BorderLayout());

    filterPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

    hideDetachedLocationsCheckBox.setSelected(true);
    java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("i18n/org/opentcs/kernelcontrolcenter/Bundle"); // NOI18N
    hideDetachedLocationsCheckBox.setText(bundle.getString("peripheralsPanel.checkBox_hideDetachedLocations.text")); // NOI18N
    hideDetachedLocationsCheckBox.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        hideDetachedLocationsCheckBoxActionPerformed(evt);
      }
    });
    filterPanel.add(hideDetachedLocationsCheckBox);

    listPanel.add(filterPanel, java.awt.BorderLayout.NORTH);

    peripheralTable.addMouseListener(new java.awt.event.MouseAdapter() {
      public void mouseClicked(java.awt.event.MouseEvent evt) {
        peripheralTableMouseClicked(evt);
      }
    });
    jScrollPane1.setViewportView(peripheralTable);

    listPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);

    add(listPanel);

    peripheralDetailsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Peripheral details"));
    peripheralDetailsPanel.setPreferredSize(new java.awt.Dimension(800, 23));
    peripheralDetailsPanel.setLayout(new java.awt.BorderLayout());
    add(peripheralDetailsPanel);

    getAccessibleContext().setAccessibleName(bundle.getString("peripheralsPanel.accessibleName")); // NOI18N
  }// </editor-fold>//GEN-END:initComponents

  private void peripheralTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_peripheralTableMouseClicked
    if (evt.getClickCount() == 2) {
      int index = peripheralTable.getSelectedRow();
      if (index >= 0) {
        PeripheralTableModel model = (PeripheralTableModel) peripheralTable.getModel();
        LocalPeripheralEntry selectedEntry
            = model.getDataAt(peripheralTable.convertRowIndexToModel(index));
        detailPanel.attachToEntry(selectedEntry);
      }
    }
  }//GEN-LAST:event_peripheralTableMouseClicked

  private void hideDetachedLocationsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hideDetachedLocationsCheckBoxActionPerformed
    updateRowFilter();
  }//GEN-LAST:event_hideDetachedLocationsCheckBoxActionPerformed

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel filterPanel;
  private javax.swing.JCheckBox hideDetachedLocationsCheckBox;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JPanel listPanel;
  private javax.swing.JPanel peripheralDetailsPanel;
  private javax.swing.JTable peripheralTable;
  // End of variables declaration//GEN-END:variables
}


<|start_filename|>openTCS-CommAdapter-Loopback/src/main/java/org/opentcs/virtualvehicle/inputcomponents/ValidationListener.java<|end_filename|>
/**
 * Copyright (c) The openTCS Authors.
 *
 * This program is free software and subject to the MIT license. (For details,
 * see the licensing information (LICENSE.txt) you should have received with
 * this copy of the software.)
 */
package org.opentcs.virtualvehicle.inputcomponents;

import java.util.EventListener;

/**
 * A listener interface for {@link ValidationEvent ValidationEvents}.
 *
 * @author <NAME> (Fraunhofer IML)
 */
public interface ValidationListener
    extends EventListener {

  /**
   * Should be called when the state of validation changed.
   *
   * @param e The ValidationEvent containing validation information.
   */
  void validityChanged(ValidationEvent e);
}
