protected ConfigurationMetadata writeMetaData() {
   ConfigurationMetadata metadata = this.metadataCollector.getMetadata();
   metadata = mergeAdditionalMetadata(metadata);
   if (!metadata.getItems().isEmpty()) {
     try {
       this.metadataStore.writeMetadata(metadata);
     } catch (IOException ex) {
       throw new IllegalStateException("Failed to write metadata", ex);
     }
     return metadata;
   }
   return null;
 }
 private ConfigurationMetadata mergeAdditionalMetadata(ConfigurationMetadata metadata) {
   try {
     ConfigurationMetadata merged = new ConfigurationMetadata(metadata);
     merged.merge(this.metadataStore.readAdditionalMetadata());
     return merged;
   } catch (FileNotFoundException ex) {
     // No additional metadata
   } catch (InvalidConfigurationMetadataException ex) {
     log(ex.getKind(), ex.getMessage());
   } catch (Exception ex) {
     logWarning("Unable to merge additional metadata");
     logWarning(getStackTrace(ex));
   }
   return metadata;
 }
 private void processNestedType(
     String prefix,
     TypeElement element,
     ExecutableElement source,
     String name,
     ExecutableElement getter,
     VariableElement field,
     TypeMirror returnType) {
   Element returnElement = this.processingEnv.getTypeUtils().asElement(returnType);
   boolean isNested = isNested(returnElement, field, element);
   AnnotationMirror annotation = getAnnotation(getter, configurationPropertiesAnnotation());
   if (returnElement != null
       && returnElement instanceof TypeElement
       && annotation == null
       && isNested) {
     String nestedPrefix = ConfigurationMetadata.nestedPrefix(prefix, name);
     this.metadataCollector.add(
         ItemMetadata.newGroup(
             nestedPrefix,
             this.typeUtils.getType(returnElement),
             this.typeUtils.getType(element),
             (getter == null ? null : getter.toString())));
     processTypeElement(nestedPrefix, (TypeElement) returnElement, source);
   }
 }