CurieAugmenter.java

/*
 * #%L
 * wcm.io
 * %%
 * Copyright (C) 2015 wcm.io
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package io.wcm.caravan.hal.docs.impl.augmenter;

import static io.wcm.caravan.hal.docs.impl.augmenter.CurieUtil.LINK_RELATION_CURIES;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.Sets;

import io.wcm.caravan.hal.resource.HalResource;
import io.wcm.caravan.hal.resource.Link;

/**
 * Checks if the HAL resource contains link relations with curies without documentaiton links.
 * Add documentation links referencing the HAL documentation generated by this bundle.
 */
class CurieAugmenter {

  private final DocsMetadata metadata;

  CurieAugmenter(DocsMetadata metadata) {
    this.metadata = metadata;
  }

  public void augment(HalResource resource) {
    Set<String> existingCurieNames = getExistingCurieNames(resource);
    Set<Link> curieLinks = getCurieLinks(resource, existingCurieNames);
    resource.addLinks(LINK_RELATION_CURIES, curieLinks);
  }

  private Set<String> getExistingCurieNames(HalResource hal) {
    if (!hal.hasLink(LINK_RELATION_CURIES)) {
      return Collections.emptySet();
    }
    return Stream.of(hal.getLink(LINK_RELATION_CURIES))
        .map(link -> link.getName())
        .collect(Collectors.toSet());
  }

  private Set<Link> getCurieLinks(HalResource resource, Set<String> existingCurieNames) {
    Set<Link> curiLinks = Sets.newLinkedHashSet();
    curiLinks.addAll(getCurieLinksForCurrentHalResource(resource, existingCurieNames));
    curiLinks.addAll(getCurieLinksForEmbeddedResources(resource, existingCurieNames));
    return curiLinks;
  }

  private List<Link> getCurieLinksForCurrentHalResource(HalResource resource, Set<String> existingCurieNames) {
    return resource.getLinks().keySet().stream()
        // get CURI name for relation
        .map(CurieUtil::getCurieName)
        // filter CURIE being empty or exist in HAL resource
        .filter(curieName -> StringUtils.isNotEmpty(curieName) && !existingCurieNames.contains(curieName))
        // get link for CURI name
        .map(this::toCurieLink)
        // filter non existing links
        .filter(link -> link != null)
        .collect(Collectors.toList());
  }

  private List<Link> getCurieLinksForEmbeddedResources(HalResource resource, Set<String> existingCurieNames) {
    return resource.getEmbedded().values().stream()
        .flatMap(embeddedResource -> getCurieLinks(embeddedResource, existingCurieNames).stream())
        .collect(Collectors.toList());
  }

  private Link toCurieLink(String curieName) {
    String docLink = metadata.getCurieLink(curieName);
    if (docLink == null) {
      return null;
    }
    else {
      return new Link(docLink).setName(curieName).setTitle("Documentation link");
    }
  }

}