# Extend ModelMap in a RuleSource plugin

**URL:** <https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546>\
**Category:** Help/Discuss\
**Created:** [January 6, 2016, 2:47am UTC](https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546 "2016-01-06T02:47:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![awrichar](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/awrichar/32/7078_2.png) [@awrichar](https://discuss.gradle.org/u/awrichar)\
**Post date:** [January 6, 2016, 2:47am UTC](https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546/1 "2016-01-06T02:47:15Z")

</div>

I’m creating a plugin (using the new rule-based syntax) which adds a new `ModelMap` container. I can get it to work, but there’s one thing I don’t understand. I’d like to declare a custom extension of `ModelMap` to streamline my code, but it doesn’t seem to work when used as an input to a `Mutate` rule.

Here is a simple example that demonstrates the problem:

```
@Managed
interface Foo {}

interface FooContainer extends ModelMap<Foo> {}

class FooRules extends RuleSource {
    @Model
    void foo(FooContainer f) {}

    @Mutate
    void createFooTasks(TaskContainer tasks, FooContainer f) {}
}

```

and a build script that uses it:

```
model {
    foo {
        item(Foo)
    }
}

```

This code gives the confusing error **“Foo is not a subtype of Foo”**. If I explicitly use `ModelMap<Foo>` instead of `FooContainer` throughout my code, it works fine. Am I missing something, or is this a bug? I’m using Gradle 2.10.

---

<div class="post-metadata">

**Author:** ![mark\_vieira](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mark_vieira/32/5396_2.png) [@mark\_vieira](https://discuss.gradle.org/u/mark_vieira)\
**Post date:** [January 6, 2016, 3:16am UTC](https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546/2 "2016-01-06T03:16:46Z")

</div>

This may very well be an issue with Gradle 2.10 (or perhaps not yet implemented). Your example however _does_ work when in the master branch so you might try using the [latest nightly](http://gradle.org/gradle-nightly-build/).

BTW, you’ll want to use `ModelMap<Task>` instead of `TaskContainer`. I believe targeting `TaskContainer` as an input/subject to a rule is likely to be deprecated/removed.

---

<div class="post-metadata">

**Author:** ![awrichar](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/awrichar/32/7078_2.png) [@awrichar](https://discuss.gradle.org/u/awrichar)\
**Post date:** [January 6, 2016, 4:38am UTC](https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546/3 "2016-01-06T04:38:47Z")

</div>

Thanks Mark, it does work with the latest nightly! But if you’re doing away with TaskContainer, I may be going the wrong direction; was mainly doing this to parallel the Container interfaces in the existing Gradle code.

To take it a step further though, it looks like I **cannot** add additional managed properties to FooContainer. I was hoping to have some top-level config that applies to all items in the map, so I tried:

```
@Managed
interface FooContainer extends ModelMap<Foo> {
    boolean getBar()
    void setBar(boolean bar)
}

```

This now gives the error **“Method FooContainer\_Impl.setBar(Z)V is abstract”**. I’m guessing this one may be by design, and `ModelMap` may be exclusively designed to contain children (with no properties of its own).

---

<div class="post-metadata">

**Author:** ![mark\_vieira](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mark_vieira/32/5396_2.png) [@mark\_vieira](https://discuss.gradle.org/u/mark_vieira)\
**Post date:** [January 6, 2016, 3:35pm UTC](https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546/4 "2016-01-06T15:35:20Z")

</div>

> [@awrichar](#):
>
> But if you’re doing away with TaskContainer, I may be going the wrong direction; was mainly doing this to parallel the Container interfaces in the existing Gradle code.

[`TaskContainer`](https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskContainer.html) is treated a bit special. You’ll notice it is a “legacy” collection and doesn’t implement `ModelMap`. We have special bridging logic to handle it.

> [@awrichar](#):
>
> To take it a step further though, it looks like I cannot add additional managed properties to FooContainer.

The managed collection types cannot be extended in that way. The “Container” types are really mostly there for additional type safety and documentation purposes. For this you could either create a new top-level model element with these properties or just use the model DSL to configure all items in the collection.

```
model {
    foo {
        all {
            // configure all `Foo`s
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![awrichar](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/awrichar/32/7078_2.png) [@awrichar](https://discuss.gradle.org/u/awrichar)\
**Post date:** [January 7, 2016, 6:36pm UTC](https://discuss.gradle.org/t/extend-modelmap-in-a-rulesource-plugin/13546/5 "2016-01-07T18:36:01Z")

</div>

Yep, this is pretty much what I ended up doing (creating a top-level element with base config and a “contents” sub-element containing the map). Thanks for all the details!
