@Override
    public Driver merge(Driver other) {
        checkArgument(parents == null || Objects.equals(parent(), other.parent()),
                      "Parent drivers are not the same");

        // Merge the behaviours.
        Map<Class<? extends Behaviour>, Class<? extends Behaviour>>
                behaviours = Maps.newHashMap();
        behaviours.putAll(this.behaviours);
        other.behaviours().forEach(b -> behaviours.put(b, other.implementation(b)));

        // Merge the properties.
        ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
        properties.putAll(other.properties());

        // remove duplicated properties from this driver and merge
        this.properties().entrySet().stream()
                .filter(e -> !other.properties().containsKey(e.getKey()))
                .forEach(properties::put);

        List<Driver> completeParents = new ArrayList<>();

        if (parents != null) {
            parents.forEach(parent -> other.parents().forEach(otherParent -> {
                if (otherParent.name().equals(parent.name())) {
                    completeParents.add(parent.merge(otherParent));
                } else if (!completeParents.contains(otherParent)) {
                    completeParents.add(otherParent);
                } else if (!completeParents.contains(parent)) {
                    completeParents.add(parent);
                }
            }));
        }
        return new DefaultDriver(name, !completeParents.isEmpty() ? completeParents : other.parents(),
                                 manufacturer, hwVersion, swVersion,
                                 ImmutableMap.copyOf(behaviours), properties.build());
    }
@Test
    public void merge() {
        DefaultDriver one = new DefaultDriver("foo.bar", new ArrayList<>(), "Circus", "lux", "1.2a",
                                              ImmutableMap.of(TestBehaviour.class,
                                                              TestBehaviourImpl.class),
                                              ImmutableMap.of("foo", "bar"));
        Driver ddc =
                one.merge(new DefaultDriver("foo.bar", new ArrayList<>(), "", "", "",
                                            ImmutableMap.of(TestBehaviourTwo.class,
                                                            TestBehaviourTwoImpl.class),
                                            ImmutableMap.of("goo", "wee")));

        assertEquals("incorrect name", "foo.bar", ddc.name());
        assertEquals("incorrect mfr", "Circus", ddc.manufacturer());
        assertEquals("incorrect hw", "lux", ddc.hwVersion());
        assertEquals("incorrect sw", "1.2a", ddc.swVersion());

        assertEquals("incorrect behaviour count", 2, ddc.behaviours().size());
        assertTrue("incorrect behaviour", ddc.hasBehaviour(TestBehaviourTwo.class));

        assertEquals("incorrect property count", 2, ddc.properties().size());
        assertEquals("incorrect key count", 2, ddc.keys().size());
        assertEquals("incorrect property", "wee", ddc.value("goo"));

        assertTrue("incorrect toString", ddc.toString().contains("Circus"));
    }