@Override
 public <T> void extract(ModelSchemaExtractionContext<T> extractionContext) {
   Type type = extractionContext.getType().getType();
   if (!(type instanceof Class)) {
     return;
   }
   Class<?> contractType = (Class<?>) type;
   if (!contractType.isInterface()) {
     return;
   }
   if (contractType.getGenericInterfaces().length != 1) {
     return;
   }
   Type superType = contractType.getGenericInterfaces()[0];
   if (!(superType instanceof ParameterizedType)) {
     return;
   }
   ParameterizedType parameterizedSuperType = (ParameterizedType) superType;
   if (!parameterizedSuperType.getRawType().equals(ModelMap.class)) {
     return;
   }
   ModelType<?> elementType = ModelType.of(parameterizedSuperType.getActualTypeArguments()[0]);
   Class<?> proxyImpl = generator.generate(ModelMapGroovyDecorator.Managed.class, contractType);
   extractionContext.found(
       new SpecializedMapSchema<T>(extractionContext.getType(), elementType, proxyImpl));
 }
 @Override
 protected <R> ModelSchema<R> createSchema(
     ModelSchemaExtractionContext<R> extractionContext,
     Iterable<ModelProperty<?>> properties,
     Set<WeaklyTypeReferencingMethod<?, ?>> nonPropertyMethods,
     Iterable<ModelSchemaAspect> aspects) {
   boolean annotated = extractionContext.getType().isAnnotationPresent(UnmanagedStruct.class);
   return new UnmanagedImplStructSchema<R>(
       extractionContext.getType(), properties, nonPropertyMethods, aspects, annotated);
 }
  private <T, E> ModelSchemaExtractionResult<T> gettModelSchemaExtractionResult(
      ModelSchemaExtractionContext<T> extractionContext,
      final ModelSchemaCache cache,
      ModelType<E> elementType,
      final ModelSchemaStore store) {
    ModelCollectionSchema<T, E> schema =
        ModelSchema.collection(
            extractionContext.getType(),
            elementType,
            new Function<ModelCollectionSchema<T, E>, NodeInitializer>() {
              @Override
              public NodeInitializer apply(ModelCollectionSchema<T, E> input) {
                final ManagedChildNodeCreatorStrategy<E> childCreator =
                    new ManagedChildNodeCreatorStrategy<E>(store);
                return new ProjectionOnlyNodeInitializer(
                    ModelMapModelProjection.managed(input.getElementType(), childCreator));
              }
            });
    ModelSchemaExtractionContext<?> typeParamExtractionContext =
        extractionContext.child(
            elementType,
            "element type",
            new Action<ModelSchemaExtractionContext<?>>() {
              public void execute(ModelSchemaExtractionContext<?> context) {
                ModelType<?> elementType = context.getType();
                ModelSchema<?> typeParamSchema = cache.get(elementType);

                if (!typeParamSchema.getKind().isManaged()) {
                  throw new InvalidManagedModelElementTypeException(
                      context.getParent(),
                      String.format(
                          "cannot create a model map of type %s as it is not a %s type.",
                          elementType, Managed.class.getName()));
                }
              }
            });
    return new ModelSchemaExtractionResult<T>(schema, ImmutableList.of(typeParamExtractionContext));
  }
 protected <R> ModelSchema<R> createSchema(
     final ModelSchemaExtractionContext<R> extractionContext,
     Iterable<ModelPropertyExtractionResult<?>> propertyResults,
     Iterable<ModelSchemaAspect> aspects) {
   Iterable<ModelProperty<?>> properties =
       Iterables.transform(
           propertyResults,
           new Function<ModelPropertyExtractionResult<?>, ModelProperty<?>>() {
             @Override
             public ModelProperty<?> apply(ModelPropertyExtractionResult<?> propertyResult) {
               return propertyResult.getProperty();
             }
           });
   return new UnmanagedImplStructSchema<R>(extractionContext.getType(), properties, aspects);
 }
  public <T> ModelSchemaExtractionResult<T> extract(
      ModelSchemaExtractionContext<T> extractionContext,
      ModelSchemaStore store,
      final ModelSchemaCache cache) {
    ModelType<T> type = extractionContext.getType();
    if (MODEL_MAP_MODEL_TYPE.isAssignableFrom(type)) {
      if (!type.getRawClass().equals(ModelMap.class)) {
        throw new InvalidManagedModelElementTypeException(
            extractionContext,
            String.format("subtyping %s is not supported.", ModelMap.class.getName()));
      }
      if (type.isHasWildcardTypeVariables()) {
        throw new InvalidManagedModelElementTypeException(
            extractionContext,
            String.format("type parameter of %s cannot be a wildcard.", ModelMap.class.getName()));
      }

      List<ModelType<?>> typeVariables = type.getTypeVariables();
      if (typeVariables.isEmpty()) {
        throw new InvalidManagedModelElementTypeException(
            extractionContext,
            String.format("type parameter of %s has to be specified.", ModelMap.class.getName()));
      }

      ModelType<?> elementType = typeVariables.get(0);

      if (MODEL_MAP_MODEL_TYPE.isAssignableFrom(elementType)) {
        throw new InvalidManagedModelElementTypeException(
            extractionContext,
            String.format(
                "%1$s cannot be used as type parameter of %1$s.", ModelMap.class.getName()));
      }

      return gettModelSchemaExtractionResult(extractionContext, cache, elementType, store);
    } else {
      return null;
    }
  }