/**
   * Performs mapping using a TypeMap if one exists, else a converter if one applies, else a newly
   * created TypeMap. Recursive entry point.
   */
  public <S, D> D map(MappingContext<S, D> context) {
    MappingContextImpl<S, D> contextImpl = (MappingContextImpl<S, D>) context;
    Class<D> destinationType = context.getDestinationType();

    // Resolve some circular dependencies
    if (!Iterables.isIterable(destinationType)) {
      D circularDest = contextImpl.destinationForSource();
      if (circularDest != null) return circularDest;
    }

    D destination = null;
    TypeMap<S, D> typeMap = typeMapStore.get(context.getSourceType(), context.getDestinationType());
    if (typeMap != null) {
      destination = typeMap(contextImpl, typeMap);
    } else {
      Converter<S, D> converter = converterFor(context);
      if (converter != null) {
        destination = convert(context, converter);
      } else {
        // Call getOrCreate in case TypeMap was created concurrently
        typeMap =
            typeMapStore.getOrCreate(context.getSourceType(), context.getDestinationType(), this);
        destination = typeMap(contextImpl, typeMap);
      }
    }

    return destination;
  }
 @SuppressWarnings("unchecked")
 private Object resolveSourceValue(MappingContextImpl<?, ?> context, Mapping mapping) {
   Object source = context.getSource();
   if (mapping instanceof PropertyMappingImpl) {
     for (Accessor accessor : (List<Accessor>) ((PropertyMapping) mapping).getSourceProperties()) {
       context.setParentSource(source);
       source = accessor.getValue(source);
       if (source == null) return null;
       if (!Iterables.isIterable(source.getClass())) {
         Object circularDest = context.sourceToDestination.get(source);
         if (circularDest != null) context.intermediateDestinations.add(circularDest);
       }
     }
   } else if (mapping instanceof ConstantMapping)
     source = ((ConstantMapping) mapping).getConstant();
   return source;
 }