private void initTagsStructure() {
    Resource defaultNamespace =
        resourceResolver.getResource(TAGS_ROOT + "/" + TagConstants.DEFAULT_NAMESPACE);
    // if it's already existing, then don't proceed any further
    if (defaultNamespace != null) {
      return;
    }
    Map<String, Object> etcProperties = new HashMap<String, Object>();
    etcProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrResourceConstants.NT_SLING_FOLDER);

    Map<String, Object> tagsProperties = new HashMap<String, Object>();
    tagsProperties.put(JcrConstants.JCR_PRIMARYTYPE, JcrResourceConstants.NT_SLING_FOLDER);
    tagsProperties.put(JcrConstants.JCR_TITLE, "Tags");
    // locale strings that are recognized languages in child tags
    tagsProperties.put(
        "languages",
        new String[] {"en", "de", "es", "fr", "it", "pt_br", "zh_cn", "ch_tw", "ja", "ko_kr"});

    try {
      ResourceUtil.getOrCreateResource(resourceResolver, "/etc", etcProperties, null, true);
      ResourceUtil.getOrCreateResource(resourceResolver, TAGS_ROOT, tagsProperties, null, true);
      createTag(TagConstants.DEFAULT_NAMESPACE_ID, "Standard Tags", null);
    } catch (PersistenceException | InvalidTagFormatException e) {
      log.error("Error creating tags tree", e);
    }
  }
  @Override
  public Tag createTag(String tagID, String title, String description, boolean autoSave)
      throws AccessControlException, InvalidTagFormatException {
    String tagPath = getPathFromID(tagID);
    Resource tagResource = resourceResolver.getResource(tagPath);
    if (tagResource != null) {
      return tagResource.adaptTo(Tag.class);
    }

    // ensure the parent exists first
    String parentTagPath = tagPath.substring(0, tagPath.lastIndexOf("/"));
    if (!TAGS_ROOT.equals(parentTagPath)) {
      createTag(parentTagPath, null, null, false);
    }

    // otherwise it needs to be made
    Map<String, Object> tagProps = new HashMap<String, Object>();
    tagProps.put(JcrConstants.JCR_PRIMARYTYPE, TagConstants.NT_TAG);
    tagProps.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, TAG_RESOURCE_TYPE);
    if (title != null) {
      tagProps.put(JcrConstants.JCR_TITLE, title);
    }
    if (description != null) {
      tagProps.put(JcrConstants.JCR_DESCRIPTION, description);
    }
    tagProps.put(NameConstants.PN_LAST_MOD, Calendar.getInstance());
    tagProps.put(NameConstants.PN_LAST_MOD_BY, resourceResolver.getUserID());

    try {
      tagResource =
          ResourceUtil.getOrCreateResource(resourceResolver, tagPath, tagProps, null, autoSave);

      return tagResource.adaptTo(Tag.class);
    } catch (PersistenceException e) {
      log.error("failed to create tag", e);
      // throw this as a failure to indicate it failed
      throw new AccessControlException("failed to create tag");
    }
  }