docs: @SuppressWarnings("deprecation")
      public boolean postValidateContentSpec(final ContentSpec contentSpec, final String username) {
  
          // Check if the app should be shutdown
          if (isShuttingDown.get()) {
              shutdown.set(true);
              return false;
          }
  
          boolean valid = true;
  
          // If editing then check that the ID exists & the CHECKSUM/SpecRevision match
          if (contentSpec.getId() != null) {
              ContentSpecWrapper contentSpecEntity = null;
              String serverContentSpec = null;
              try {
                  contentSpecEntity = contentSpecProvider.getContentSpec(contentSpec.getId(), contentSpec.getRevision());
                  final TextContentSpecWrapper textContentSpecEntity = textContentSpecProvider.getTextContentSpec(contentSpec.getId(),
                          contentSpec.getRevision());
                  if (textContentSpecEntity != null) {
                      serverContentSpec = textContentSpecEntity.getText();
                  }
              } catch (NotFoundException e) {
  
              }
              if (contentSpecEntity == null || serverContentSpec == null) {
                  log.error(String.format(ProcessorConstants.ERROR_INVALID_CS_ID_MSG, "ID = " + contentSpec.getId()));
                  valid = false;
              } else {
                  // Check that the checksum is valid
                  if (!processingOptions.isIgnoreChecksum()) {
                      final String currentChecksum = HashUtilities.generateMD5(ContentSpecUtilities.removeChecksum(serverContentSpec));
                      if (contentSpec.getChecksum() != null) {
                          if (!contentSpec.getChecksum().equals(currentChecksum)) {
                              log.error(String.format(ProcessorConstants.ERROR_CS_NONMATCH_CHECKSUM_MSG, contentSpec.getChecksum(),
                                      currentChecksum));
                              valid = false;
                          }
                      } else {
                          log.error(String.format(ProcessorConstants.ERROR_CS_NONMATCH_CHECKSUM_MSG, null, currentChecksum));
                          valid = false;
                      }
                  }
  
                  // Check that the Content Spec isn't read only
                  if (contentSpecEntity.getProperty(serverEntities.getReadOnlyPropertyTagId()) != null) {
                      if (!contentSpecEntity.getProperty(serverEntities.getReadOnlyPropertyTagId()).getValue().matches(
                              "(^|.*,)" + username + "(,.*|$)")) {
                          log.error(ProcessorConstants.ERROR_CS_READ_ONLY_MSG);
                          valid = false;
                      }
                  }
              }
          }
  
          // Check that the content spec locale is valid
          if (!isNullOrEmpty(contentSpec.getLocale())) {
              final LocaleWrapper locale = EntityUtilities.findLocaleFromString(serverSettings.getLocales(), contentSpec.getLocale());
              if (locale == null) {
                  log.error(ProcessorConstants.ERROR_CS_INVALID_LOCALE_MSG);
                  valid = false;
              }
          }
  
          // Check that the injection options are valid
          if (contentSpec.getInjectionOptions() != null) {
              for (final String injectionType : contentSpec.getInjectionOptions().getStrictTopicTypes()) {
                  TagWrapper tag = null;
                  try {
                      tag = tagProvider.getTagByName(injectionType);
                  } catch (NotFoundException e) {
  
                  }
                  if (tag != null) {
                      if (!tag.containedInCategory(serverEntities.getTypeCategoryId())) {
                          log.error(String.format(ProcessorConstants.ERROR_INVALID_INJECTION_TYPE_MSG, injectionType));
                          valid = false;
                      }
                  } else {
                      log.error(String.format(ProcessorConstants.ERROR_INVALID_INJECTION_TYPE_MSG, injectionType));
                      valid = false;
                  }
              }
          }
  
          // Check that any metadata topics are valid
          if (contentSpec.getRevisionHistory() != null && !postValidateTopic(contentSpec.getRevisionHistory(), contentSpec)) {
              valid = false;
          }
          if (contentSpec.getFeedback() != null && !postValidateTopic(contentSpec.getFeedback(), contentSpec)) {
              valid = false;
          }
          if (contentSpec.getLegalNotice() != null && !postValidateTopic(contentSpec.getLegalNotice(), contentSpec)) {
              valid = false;
          }
          if (contentSpec.getAuthorGroup() != null && !postValidateTopic(contentSpec.getAuthorGroup(), contentSpec)) {
              valid = false;
          }
          if (contentSpec.getAbstractTopic() != null && !postValidateTopic(contentSpec.getAbstractTopic(), contentSpec)) {
              valid = false;
          }
  
          // Validate that the files exist
          if (contentSpec.getFiles() != null) {
              if (!validateFiles(contentSpec)) {
                  valid = false;
              }
          }
  
          // Make sure that the abstract is valid docbook xml
          if (!isNullOrEmpty(contentSpec.getAbstract())) {
              String wrappedAbstract = contentSpec.getAbstract();
              if (!contentSpec.getAbstract().matches("^<(formal|sim)?para>(.|\\s)*")) {
                  wrappedAbstract = "<para>" + contentSpec.getAbstract() + "</para>";
              }
              wrappedAbstract = "<abstract>" + wrappedAbstract + "</abstract>";
  
              if (!postValidateXML(contentSpec, contentSpec.getAbstractNode(), wrappedAbstract, "abstract")) {
                  valid = false;
              }
          }
  
          // Check to make sure the relevant keyvalue nodes have valid xml
          for (final Node node : contentSpec.getNodes()) {
              if (node instanceof KeyValueNode) {
                  final KeyValueNode keyValueNode = (KeyValueNode) node;
                  if (!isNullOrEmpty(keyValueNode.getKey())) {
                      final Object value = keyValueNode.getValue();
                      // Make sure that the metadata is valid XML if it might be used
                      if (value instanceof String && !isNullOrEmpty((String) value)
                              && ProcessorConstants.METADATA_DOCBOOK_ELEMENTS.containsKey(keyValueNode.getKey())) {
                          String element = ProcessorConstants.METADATA_DOCBOOK_ELEMENTS.get(keyValueNode.getKey());
  
                          final String wrappedElement;
                          if ("para".equals(element)) {
                              wrappedElement = "<abstract><" + element + ">" + value + "</" + element + "></abstract>";
                              element = "abstract";
                          } else {
                              wrappedElement = "<" + element + ">" + value + "</" + element + ">";
                          }
  
                          if (!postValidateXML(contentSpec, keyValueNode, wrappedElement, element)) {
                              valid = false;
                          }
                      }
                  }
              }
          }
  
          // Check that each level is valid
          if (!postValidateLevel(contentSpec.getBaseLevel(), contentSpec)) {
              valid = false;
          }
  
          return valid;
      }