gt:             if (canvas != null) {
context: /**
   * This file is part of the Goobi viewer - a content presentation and management application for digitized objects.
   *
   * Visit these websites for more information.
   *          - http://www.intranda.com
   *          - http://digiverso.com
   *
   * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
   */
  package io.goobi.viewer.api.rest.resourcebuilders;
  
  import static io.goobi.viewer.api.rest.v1.ApiUrls.RECORDS_CMDI_LANG;
  import static io.goobi.viewer.api.rest.v1.ApiUrls.RECORDS_RECORD;
  import static io.goobi.viewer.api.rest.v1.ApiUrls.RECORDS_TEI_LANG;
  
  import java.io.IOException;
  import java.net.URI;
  import java.net.URISyntaxException;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.List;
  import java.util.Map;
  import java.util.Optional;
  
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.commons.lang3.StringUtils;
  import org.apache.solr.common.SolrDocument;
  import org.apache.solr.common.SolrDocumentList;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import de.intranda.api.annotation.oa.Motivation;
  import de.intranda.api.iiif.IIIFUrlResolver;
  import de.intranda.api.iiif.image.ImageInformation;
  import de.intranda.api.iiif.presentation.IPresentationModelElement;
  import de.intranda.api.iiif.presentation.content.ImageContent;
  import de.intranda.api.iiif.presentation.enums.AnnotationType;
  import de.intranda.api.iiif.presentation.v2.AbstractPresentationModelElement2;
  import de.intranda.api.iiif.presentation.v2.AnnotationList;
  import de.intranda.api.iiif.presentation.v2.Canvas2;
  import de.intranda.api.iiif.presentation.v2.Collection2;
  import de.intranda.api.iiif.presentation.v2.Layer;
  import de.intranda.api.iiif.presentation.v2.Manifest2;
  import de.intranda.api.iiif.presentation.v2.Range2;
  import de.intranda.api.iiif.presentation.v2.Sequence;
  import de.unigoettingen.sub.commons.contentlib.exceptions.ContentNotFoundException;
  import de.unigoettingen.sub.commons.contentlib.exceptions.IllegalRequestException;
  import io.goobi.viewer.api.rest.AbstractApiUrlManager;
  import io.goobi.viewer.controller.DataManager;
  import io.goobi.viewer.exceptions.DAOException;
  import io.goobi.viewer.exceptions.IndexUnreachableException;
  import io.goobi.viewer.exceptions.PresentationException;
  import io.goobi.viewer.exceptions.ViewerConfigurationException;
  import io.goobi.viewer.managedbeans.utils.BeanUtils;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.BuildMode;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.CollectionBuilder;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.LayerBuilder;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.ManifestBuilder;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.OpenAnnotationBuilder;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.SequenceBuilder;
  import io.goobi.viewer.model.iiif.presentation.v2.builder.StructureBuilder;
  import io.goobi.viewer.model.search.SearchHelper;
  import io.goobi.viewer.model.viewer.BrowseDcElement;
  import io.goobi.viewer.model.viewer.PageType;
  import io.goobi.viewer.model.viewer.PhysicalElement;
  import io.goobi.viewer.model.viewer.StringPair;
  import io.goobi.viewer.model.viewer.StructElement;
  import io.goobi.viewer.solr.SolrConstants;
  import io.goobi.viewer.solr.SolrTools;
  
  /**
   * @author florian
   *
   */
  public class IIIFPresentation2ResourceBuilder {
  
      private static final Logger logger = LoggerFactory.getLogger(IIIFPresentation2ResourceBuilder.class);
  
      private ManifestBuilder manifestBuilder;
      private StructureBuilder structureBuilder;
      private SequenceBuilder sequenceBuilder;
      private LayerBuilder layerBuilder;
      private CollectionBuilder collectionBuilder;
      private final AbstractApiUrlManager urls;
      private final HttpServletRequest request;
  
      public IIIFPresentation2ResourceBuilder(AbstractApiUrlManager urls, HttpServletRequest request) {
          this.urls = urls;
          this.request = request;
      }
  
      public IPresentationModelElement getManifest(String pi, BuildMode mode) throws PresentationException, IndexUnreachableException,
              ContentNotFoundException, URISyntaxException, ViewerConfigurationException, DAOException {
          getManifestBuilder().setBuildMode(mode);
          getSequenceBuilder().setBuildMode(mode);
          List<StructElement> docs = BuildMode.IIIF.equals(mode) || BuildMode.THUMBS.equals(mode) ? getManifestBuilder().getDocumentWithChildren(pi)
                  : Arrays.asList(getManifestBuilder().getDocument(pi));
          if (docs.isEmpty()) {
              throw new ContentNotFoundException("No document found for pi " + pi);
          }
          StructElement mainDoc = docs.get(0);
          IPresentationModelElement manifest = getManifestBuilder().generateManifest(mainDoc);
  
          if (manifest instanceof Collection2 && docs.size() > 1) {
              getManifestBuilder().addVolumes((Collection2) manifest, docs.subList(1, docs.size()));
          } else if (manifest instanceof Manifest2) {
              getManifestBuilder().addAnchor((Manifest2) manifest, mainDoc.getMetadataValue(SolrConstants.PI_ANCHOR));
  
              getSequenceBuilder().addBaseSequence((Manifest2) manifest, mainDoc, manifest.getId().toString(), request);
  
              String topLogId = mainDoc.getMetadataValue(SolrConstants.LOGID);
              if (StringUtils.isNotBlank(topLogId)) {
                  if (BuildMode.IIIF.equals(mode)) {
                      List<Range2> ranges = getStructureBuilder().generateStructure(docs, pi, false);
                      ranges.forEach(range -> {
                          ((Manifest2) manifest).addStructure(range);
                      });
                  }
              }
          }
  
          return manifest;
      }
  
      public Range2 getRange(String pi, String logId) throws PresentationException, IndexUnreachableException,
              ContentNotFoundException, URISyntaxException, ViewerConfigurationException, DAOException {
          List<StructElement> docs = getStructureBuilder().getDocumentWithChildren(pi);
  
          if (docs.isEmpty()) {
              throw new ContentNotFoundException("Not document with PI = " + pi + " and logId = " + logId + " found");
          }
          List<Range2> ranges = getStructureBuilder().generateStructure(docs, pi, false);
          Optional<Range2> range = ranges.stream().filter(r -> r.getId().toString().contains(logId + "/")).findFirst();
          return range.orElseThrow(() -> new ContentNotFoundException("Not document with PI = " + pi + " and logId = " + logId + " found"));
      }
  
      public Sequence getBaseSequence(String pi, BuildMode buildMode, String preferedViewName)
              throws PresentationException, IndexUnreachableException, URISyntaxException,
              ViewerConfigurationException, DAOException, IllegalRequestException, ContentNotFoundException {
  
          StructElement doc = getManifestBuilder().getDocument(pi);
          PageType preferedView = getPreferedPageTypeForCanvas(preferedViewName);
  
          IPresentationModelElement manifest = new ManifestBuilder(urls).setBuildMode(buildMode).generateManifest(doc);
  
          if (manifest instanceof Collection2) {
              throw new IllegalRequestException("Identifier refers to a collection which does not have a sequence");
          } else if (manifest instanceof Manifest2) {
              new SequenceBuilder(urls).setBuildMode(buildMode)
                      .setPreferedView(preferedView)
                      .addBaseSequence((Manifest2) manifest, doc, manifest.getId().toString(), request);
              return ((Manifest2) manifest).getSequences().get(0);
          }
          throw new ContentNotFoundException("Not manifest with identifier " + pi + " found");
  
      }
  
      /**
       * @param preferedViewName
       * @return
       */
      public PageType getPreferedPageTypeForCanvas(String preferedViewName) {
          PageType preferedView = PageType.viewObject;
          if (StringUtils.isNotBlank(preferedViewName)) {
              preferedView = PageType.getByName(preferedViewName);
              if (preferedView == PageType.other) {
                  preferedView = PageType.viewObject;
              }
          }
          return preferedView;
      }
  
      public Layer getLayer(String pi, String typeName, BuildMode buildMode) throws PresentationException, IndexUnreachableException,
              URISyntaxException, ViewerConfigurationException, DAOException, ContentNotFoundException, IllegalRequestException, IOException {
          StructElement doc = getStructureBuilder().getDocument(pi);
          AnnotationType type = AnnotationType.valueOf(typeName.toUpperCase());
          if (type == null) {
              throw new IllegalRequestException("No valid annotation type: " + typeName);
          }
          if (doc == null) {
              throw new ContentNotFoundException("Not document with PI = " + pi + " found");
          } else if (AnnotationType.TEI.equals(type)) {
              return getLayerBuilder().createAnnotationLayer(pi, type, Motivation.PAINTING, (id, repo) -> new TextResourceBuilder().getTEIFiles(id),
                      (id, lang) -> urls.path(RECORDS_RECORD, RECORDS_TEI_LANG).params(id, lang).buildURI());
          } else if (AnnotationType.CMDI.equals(type)) {
              return getLayerBuilder().createAnnotationLayer(pi, type, Motivation.DESCRIBING, (id, repo) -> new TextResourceBuilder().getCMDIFiles(id),
                      (id, lang) -> urls.path(RECORDS_RECORD, RECORDS_CMDI_LANG).params(id, lang).buildURI());
  
          } else {
              Map<AnnotationType, List<AnnotationList>> annoLists = getSequenceBuilder().addBaseSequence(null, doc, "", request);
              Layer layer = getLayerBuilder().generateLayer(pi, annoLists, type);
              return layer;
          }
      }
  
      /**
       * @param pi
       * @param pageNo
       * @return
       * @throws ViewerConfigurationException
       * @throws URISyntaxException
       * @throws ContentNotFoundException
       * @throws IndexUnreachableException
       * @throws PresentationException
       * @throws DAOException
       */
      public IPresentationModelElement getCanvas(String pi, Integer pageNo) throws URISyntaxException, ViewerConfigurationException,
              ContentNotFoundException, PresentationException, IndexUnreachableException, DAOException {
          StructElement doc = getManifestBuilder().getDocument(pi);
          if (doc != null) {
              PhysicalElement page = getSequenceBuilder().getPage(doc, pageNo);
              Canvas2 canvas = getSequenceBuilder().generateCanvas(doc.getPi(), page);
  