public List<FieldMetadata> getFields() {
   final List<FieldMetadata> result = new ArrayList<FieldMetadata>();
   for (final MemberHoldingTypeDetails memberHoldingTypeDetails : details) {
     result.addAll(memberHoldingTypeDetails.getDeclaredFields());
   }
   return result;
 }
 public MemberDetailsBuilder(final MemberDetails memberDetails) {
   this.originalMemberDetails = memberDetails;
   for (MemberHoldingTypeDetails memberHoldingTypeDetails : memberDetails.getDetails()) {
     memberHoldingTypeDetailsMap.put(
         memberHoldingTypeDetails.getDeclaredByMetadataId(), memberHoldingTypeDetails);
   }
 }
 public List<String> getDynamicFinderNames() {
   final List<String> dynamicFinderNames = new ArrayList<String>();
   for (final MemberHoldingTypeDetails mhtd : details) {
     dynamicFinderNames.addAll(mhtd.getDynamicFinderNames());
   }
   return dynamicFinderNames;
 }
 public List<ConstructorMetadata> getConstructors() {
   final List<ConstructorMetadata> result = new ArrayList<ConstructorMetadata>();
   for (final MemberHoldingTypeDetails memberHoldingTypeDetails : details) {
     result.addAll(memberHoldingTypeDetails.getDeclaredConstructors());
   }
   return result;
 }
 public MemberDetailsBuilder(
     final Collection<? extends MemberHoldingTypeDetails> memberHoldingTypeDetailsList) {
   this.originalMemberDetails = new MemberDetailsImpl(memberHoldingTypeDetailsList);
   for (MemberHoldingTypeDetails memberHoldingTypeDetails : originalMemberDetails.getDetails()) {
     memberHoldingTypeDetailsMap.put(
         memberHoldingTypeDetails.getDeclaredByMetadataId(), memberHoldingTypeDetails);
   }
 }
 private TypeDetailsBuilder getTypeDetailsBuilder(
     final MemberHoldingTypeDetails memberHoldingTypeDetails) {
   if (typeDetailsBuilderMap.containsKey(memberHoldingTypeDetails.getDeclaredByMetadataId())) {
     return typeDetailsBuilderMap.get(memberHoldingTypeDetails.getDeclaredByMetadataId());
   }
   TypeDetailsBuilder typeDetailsBuilder = new TypeDetailsBuilder(memberHoldingTypeDetails);
   typeDetailsBuilderMap.put(
       memberHoldingTypeDetails.getDeclaredByMetadataId(), typeDetailsBuilder);
   return typeDetailsBuilder;
 }
 public AnnotationMetadata getAnnotation(final JavaType type) {
   Validate.notNull(type, "Annotation type to locate required");
   for (final MemberHoldingTypeDetails memberHoldingTypeDetails : details) {
     final AnnotationMetadata md = memberHoldingTypeDetails.getAnnotation(type);
     if (md != null) {
       return md;
     }
   }
   return null;
 }
 /**
  * Returns the {@link JavaType} from the specified {@link MemberDetails} object;
  *
  * <p>If the found type is abstract the next {@link MemberHoldingTypeDetails} is searched.
  *
  * @param memberDetails the {@link MemberDetails} to search (required)
  * @return the first non-abstract JavaType, or null if not found
  */
 private JavaType getConcreteJavaType(MemberDetails memberDetails) {
   Assert.notNull(memberDetails, "Member details required");
   JavaType javaType = null;
   for (MemberHoldingTypeDetails memberHoldingTypeDetails : memberDetails.getDetails()) {
     if (Modifier.isAbstract(memberHoldingTypeDetails.getModifier())) {
       continue;
     }
     javaType = memberHoldingTypeDetails.getName();
   }
   return javaType;
 }
 private void doModification(final MemberHoldingTypeDetails type, final CustomData customData) {
   MemberHoldingTypeDetails memberHoldingTypeDetails =
       memberHoldingTypeDetailsMap.get(type.getDeclaredByMetadataId());
   if (memberHoldingTypeDetails != null) {
     if (memberHoldingTypeDetails.getName().equals(type.getName())
         && !memberHoldingTypeDetails.getCustomData().keySet().containsAll(customData.keySet())) {
       TypeDetailsBuilder typeDetailsBuilder = getTypeDetailsBuilder(memberHoldingTypeDetails);
       typeDetailsBuilder.getCustomData().append(customData);
       changed = true;
     }
   }
 }
 private void doModification(final FieldMetadata field, final CustomData customData) {
   MemberHoldingTypeDetails memberHoldingTypeDetails =
       memberHoldingTypeDetailsMap.get(field.getDeclaredByMetadataId());
   if (memberHoldingTypeDetails != null) {
     FieldMetadata matchedField = memberHoldingTypeDetails.getField(field.getFieldName());
     if (matchedField != null
         && !matchedField.getCustomData().keySet().containsAll(customData.keySet())) {
       TypeDetailsBuilder typeDetailsBuilder = getTypeDetailsBuilder(memberHoldingTypeDetails);
       typeDetailsBuilder.addDataToField(field, customData);
       changed = true;
     }
   }
 }
 public boolean isRequestingAnnotatedWith(
     final AnnotationMetadata annotationMetadata, final String requestingMid) {
   for (final MemberHoldingTypeDetails memberHoldingTypeDetails : details) {
     if (MemberFindingUtils.getAnnotationOfType(
             memberHoldingTypeDetails.getAnnotations(), annotationMetadata.getAnnotationType())
         != null) {
       if (memberHoldingTypeDetails.getDeclaredByMetadataId().equals(requestingMid)) {
         return true;
       }
     }
   }
   return false;
 }
  /**
   * Assists creating a local metadata identification string (MID) from any presented {@link
   * MemberHoldingTypeDetails} implementation. This is achieved by extracting the {@link
   * IdentifiableJavaStructure#getDeclaredByMetadataId()} and converting it into a {@link JavaType}
   * and {@link Path}, then calling {@link #createLocalIdentifier(JavaType, Path)}.
   *
   * @param memberHoldingTypeDetails the member holder from which the declaring type information
   *     should be extracted (required)
   * @return a MID produced by {@link #createLocalIdentifier(JavaType, Path)} for the extracted Java
   *     type in the extract Path (never null)
   */
  protected String getLocalMid(final MemberHoldingTypeDetails memberHoldingTypeDetails) {
    JavaType governorType = memberHoldingTypeDetails.getName();

    // Extract out the metadata provider class (we need this later to extract just the Path it is
    // located in)
    String providesType =
        MetadataIdentificationUtils.getMetadataClass(
            memberHoldingTypeDetails.getDeclaredByMetadataId());
    ContextualPath path =
        PhysicalTypeIdentifierNamingUtils.getPath(
            providesType, memberHoldingTypeDetails.getDeclaredByMetadataId());
    // Produce the local MID we're going to use to make the request
    return createLocalIdentifier(governorType, path);
  }
 private void doModification(final ConstructorMetadata constructor, final CustomData customData) {
   MemberHoldingTypeDetails memberHoldingTypeDetails =
       memberHoldingTypeDetailsMap.get(constructor.getDeclaredByMetadataId());
   if (memberHoldingTypeDetails != null) {
     ConstructorMetadata matchedConstructor =
         memberHoldingTypeDetails.getDeclaredConstructor(
             AnnotatedJavaType.convertFromAnnotatedJavaTypes(constructor.getParameterTypes()));
     if (matchedConstructor != null
         && !matchedConstructor.getCustomData().keySet().containsAll(customData.keySet())) {
       TypeDetailsBuilder typeDetailsBuilder = getTypeDetailsBuilder(memberHoldingTypeDetails);
       typeDetailsBuilder.addDataToConstructor(constructor, customData);
       changed = true;
     }
   }
 }
 private void doModification(final MethodMetadata method, final CustomData customData) {
   MemberHoldingTypeDetails memberHoldingTypeDetails =
       memberHoldingTypeDetailsMap.get(method.getDeclaredByMetadataId());
   if (memberHoldingTypeDetails != null) {
     MethodMetadata matchedMethod =
         memberHoldingTypeDetails.getMethod(
             method.getMethodName(),
             AnnotatedJavaType.convertFromAnnotatedJavaTypes(method.getParameterTypes()));
     if (matchedMethod != null
         && !matchedMethod.getCustomData().keySet().containsAll(customData.keySet())) {
       TypeDetailsBuilder typeDetailsBuilder = getTypeDetailsBuilder(memberHoldingTypeDetails);
       typeDetailsBuilder.addDataToMethod(method, customData);
       changed = true;
     }
   }
 }
  @Override
  protected ItdTypeDetailsProvidingMetadataItem getMetadata(
      final String metadataIdentificationString,
      final JavaType aspectName,
      final PhysicalTypeMetadata governorPhysicalTypeMetadata,
      final String itdFilename) {
    // We need to parse the annotation, which we expect to be present
    final WebJsonAnnotationValues annotationValues =
        new WebJsonAnnotationValues(governorPhysicalTypeMetadata);
    if (!annotationValues.isAnnotationFound()
        || annotationValues.getJsonObject() == null
        || governorPhysicalTypeMetadata.getMemberHoldingTypeDetails() == null) {
      return null;
    }

    // Lookup the form backing object's metadata
    final JavaType jsonObject = annotationValues.getJsonObject();
    final ClassOrInterfaceTypeDetails jsonTypeDetails =
        typeLocationService.getTypeDetails(jsonObject);
    if (jsonTypeDetails == null) {
      return null;
    }
    final LogicalPath jsonObjectPath =
        PhysicalTypeIdentifier.getPath(jsonTypeDetails.getDeclaredByMetadataId());
    final JsonMetadata jsonMetadata =
        (JsonMetadata)
            metadataService.get(JsonMetadata.createIdentifier(jsonObject, jsonObjectPath));
    if (jsonMetadata == null) {
      return null;
    }

    final PhysicalTypeMetadata backingObjectPhysicalTypeMetadata =
        (PhysicalTypeMetadata)
            metadataService.get(
                PhysicalTypeIdentifier.createIdentifier(
                    jsonObject, typeLocationService.getTypePath(jsonObject)));
    Validate.notNull(
        backingObjectPhysicalTypeMetadata,
        "Unable to obtain physical type metadata for type %s",
        jsonObject.getFullyQualifiedTypeName());
    final MemberDetails formBackingObjectMemberDetails =
        getMemberDetails(backingObjectPhysicalTypeMetadata);
    final MemberHoldingTypeDetails backingMemberHoldingTypeDetails =
        MemberFindingUtils.getMostConcreteMemberHoldingTypeDetailsWithTag(
            formBackingObjectMemberDetails, CustomDataKeys.PERSISTENT_TYPE);
    if (backingMemberHoldingTypeDetails == null) {
      return null;
    }

    // We need to be informed if our dependent metadata changes
    metadataDependencyRegistry.registerDependency(
        backingMemberHoldingTypeDetails.getDeclaredByMetadataId(), metadataIdentificationString);

    final Set<FinderMetadataDetails> finderDetails =
        webMetadataService.getDynamicFinderMethodsAndFields(
            jsonObject, formBackingObjectMemberDetails, metadataIdentificationString);
    if (finderDetails == null) {
      return null;
    }
    final Map<MethodMetadataCustomDataKey, MemberTypeAdditions> persistenceAdditions =
        webMetadataService.getCrudAdditions(jsonObject, metadataIdentificationString);
    final JavaTypePersistenceMetadataDetails javaTypePersistenceMetadataDetails =
        webMetadataService.getJavaTypePersistenceMetadataDetails(
            jsonObject, getMemberDetails(jsonObject), metadataIdentificationString);
    final PluralMetadata pluralMetadata =
        (PluralMetadata)
            metadataService.get(
                PluralMetadata.createIdentifier(
                    jsonObject, typeLocationService.getTypePath(jsonObject)));
    if (persistenceAdditions.isEmpty()
        || javaTypePersistenceMetadataDetails == null
        || pluralMetadata == null) {
      return null;
    }

    // Maintain a list of entities that are being tested
    managedEntityTypes.put(jsonObject, metadataIdentificationString);

    return new WebJsonMetadata(
        metadataIdentificationString,
        aspectName,
        governorPhysicalTypeMetadata,
        annotationValues,
        persistenceAdditions,
        javaTypePersistenceMetadataDetails.getIdentifierField(),
        pluralMetadata.getPlural(),
        finderDetails,
        jsonMetadata,
        introduceLayerComponents(governorPhysicalTypeMetadata));
  }