LinkArgs.java

  1. /*
  2.  * #%L
  3.  * wcm.io
  4.  * %%
  5.  * Copyright (C) 2014 wcm.io
  6.  * %%
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *      http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  * #L%
  19.  */
  20. package io.wcm.handler.link;

  21. import java.util.HashMap;
  22. import java.util.Map;

  23. import io.wcm.handler.url.VanityMode;
  24. import org.apache.commons.lang3.ArrayUtils;
  25. import org.apache.commons.lang3.builder.EqualsBuilder;
  26. import org.apache.commons.lang3.builder.HashCodeBuilder;
  27. import org.apache.commons.lang3.builder.ToStringBuilder;
  28. import org.apache.sling.api.resource.ValueMap;
  29. import org.apache.sling.api.wrappers.ValueMapDecorator;
  30. import org.jetbrains.annotations.NotNull;
  31. import org.jetbrains.annotations.Nullable;
  32. import org.osgi.annotation.versioning.ProviderType;

  33. import io.wcm.handler.url.UrlHandler;
  34. import io.wcm.handler.url.UrlMode;
  35. import io.wcm.wcm.commons.util.ToStringStyle;

  36. /**
  37.  * Holds parameters to influence the link resolving process.
  38.  */
  39. @ProviderType
  40. public final class LinkArgs implements Cloneable {

  41.   private UrlMode urlMode;
  42.   private VanityMode vanityMode;
  43.   private boolean dummyLink;
  44.   private String dummyLinkUrl;
  45.   private String selectors;
  46.   private String extension;
  47.   private String suffix;
  48.   private String queryString;
  49.   private String fragment;
  50.   private String windowTarget;
  51.   private boolean disableSuffixSelector;
  52.   private ValueMap properties;
  53.   private String[] linkTargetUrlFallbackProperty;
  54.   private String[] linkTargetWindowTargetFallbackProperty;


  55.   /**
  56.    * @return URL mode for externalizing the URL
  57.    */
  58.   public @Nullable UrlMode getUrlMode() {
  59.     return this.urlMode;
  60.   }

  61.   /**
  62.    * @return Vanity mode for building the URL
  63.    */
  64.   public @Nullable VanityMode getVanityMode() {
  65.     return this.vanityMode;
  66.   }

  67.   /**
  68.    * @param value URL mode for externalizing the URL
  69.    * @return this
  70.    */
  71.   public @NotNull LinkArgs urlMode(@Nullable UrlMode value) {
  72.     this.urlMode = value;
  73.     return this;
  74.   }

  75.   /**
  76.    * @param value Vanity mode for building the URL
  77.    * @return this
  78.    */
  79.   public @NotNull LinkArgs vanityMode(@Nullable VanityMode value) {
  80.     this.vanityMode = value;
  81.     return this;
  82.   }

  83.   /**
  84.    * @return If set to true, link handler returns a dummy link in edit mode when link is invalid.
  85.    */
  86.   public boolean isDummyLink() {
  87.     return this.dummyLink;
  88.   }

  89.   /**
  90.    * @param value If set to true, link handler returns a dummy link in edit mode when link is invalid.
  91.    * @return this
  92.    */
  93.   public @NotNull LinkArgs dummyLink(boolean value) {
  94.     this.dummyLink = value;
  95.     return this;
  96.   }

  97.   /**
  98.    * @return Custom dummy link url. If null default dummy url is used.
  99.    */
  100.   public @Nullable String getDummyLinkUrl() {
  101.     return this.dummyLinkUrl;
  102.   }

  103.   /**
  104.    * @param value Custom dummy link url. If null default dummy url is used.
  105.    * @return this
  106.    */
  107.   public @NotNull LinkArgs dummyLinkUrl(@Nullable String value) {
  108.     this.dummyLinkUrl = value;
  109.     return this;
  110.   }

  111.   /**
  112.    * @return Selector string
  113.    */
  114.   public @Nullable String getSelectors() {
  115.     return this.selectors;
  116.   }

  117.   /**
  118.    * @param value Selector string
  119.    * @return this
  120.    */
  121.   public @NotNull LinkArgs selectors(@Nullable String value) {
  122.     this.selectors = value;
  123.     return this;
  124.   }

  125.   /**
  126.    * @return File extension
  127.    */
  128.   public @Nullable String getExtension() {
  129.     return this.extension;
  130.   }

  131.   /**
  132.    * @param value File extension
  133.    * @return this
  134.    */
  135.   public @NotNull LinkArgs extension(@Nullable String value) {
  136.     this.extension = value;
  137.     return this;
  138.   }

  139.   /**
  140.    * @return Suffix string
  141.    */
  142.   public @Nullable String getSuffix() {
  143.     return this.suffix;
  144.   }

  145.   /**
  146.    * @param value Suffix string
  147.    * @return this
  148.    */
  149.   public @NotNull LinkArgs suffix(@Nullable String value) {
  150.     this.suffix = value;
  151.     return this;
  152.   }

  153.   /**
  154.    * @return Query parameters string (properly url-encoded)
  155.    */
  156.   public @Nullable String getQueryString() {
  157.     return this.queryString;
  158.   }

  159.   /**
  160.    * @param value Query parameters string (properly url-encoded)
  161.    * @return this
  162.    */
  163.   public @NotNull LinkArgs queryString(@Nullable String value) {
  164.     this.queryString = value;
  165.     return this;
  166.   }

  167.   /**
  168.    * @return Fragment identifier
  169.    */
  170.   public @Nullable String getFragment() {
  171.     return this.fragment;
  172.   }

  173.   /**
  174.    * @param value Fragment identifier
  175.    * @return this
  176.    */
  177.   public @NotNull LinkArgs fragment(@Nullable String value) {
  178.     this.fragment = value;
  179.     return this;
  180.   }

  181.   /**
  182.    * @return Link window target
  183.    */
  184.   public @Nullable String getWindowTarget() {
  185.     return this.windowTarget;
  186.   }

  187.   /**
  188.    * @param value Link window target
  189.    * @return this
  190.    */
  191.   public @NotNull LinkArgs windowTarget(@Nullable String value) {
  192.     this.windowTarget = value;
  193.     return this;
  194.   }

  195.   /**
  196.    * Disable the automatic addition of an additional selector {@link UrlHandler#SELECTOR_SUFFIX}
  197.    * in case a suffix is present for building the URL. Although recommended as best practice, this can
  198.    * be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk
  199.    * for file name clashes in dispatcher cache.
  200.    * @return If set to true, no additional suffix selector is added
  201.    */
  202.   public boolean isDisableSuffixSelector() {
  203.     return this.disableSuffixSelector;
  204.   }

  205.   /**
  206.    * Disable the automatic addition of an additional selector {@link UrlHandler#SELECTOR_SUFFIX}
  207.    * in case a suffix is present for building the URL. Although recommended as best practice, this can
  208.    * be omitted if you are sure your URLs are always either include a suffix or never do, so there is no risk
  209.    * for file name clashes in dispatcher cache.
  210.    * @param value If set to true, no additional suffix selector is added
  211.    * @return this
  212.    */
  213.   public @NotNull LinkArgs disableSuffixSelector(boolean value) {
  214.     this.disableSuffixSelector = value;
  215.     return this;
  216.   }

  217.   /**
  218.    * Custom properties that my be used by application-specific markup builders or processors.
  219.    * @param map Property map. Is merged with properties already set.
  220.    * @return this
  221.    */
  222.   @SuppressWarnings({ "null", "unused" })
  223.   public @NotNull LinkArgs properties(@NotNull Map<String, Object> map) {
  224.     if (map == null) {
  225.       throw new IllegalArgumentException("Map argument must not be null.");
  226.     }
  227.     getProperties().putAll(map);
  228.     return this;
  229.   }

  230.   /**
  231.    * Custom properties that my be used by application-specific markup builders or processors.
  232.    * @param key Property key
  233.    * @param value Property value
  234.    * @return this
  235.    */
  236.   @SuppressWarnings({ "null", "unused" })
  237.   public @NotNull LinkArgs property(@NotNull String key, @Nullable Object value) {
  238.     if (key == null) {
  239.       throw new IllegalArgumentException("Key argument must not be null.");
  240.     }
  241.     getProperties().put(key, value);
  242.     return this;
  243.   }

  244.   /**
  245.    * Custom properties that my be used by application-specific markup builders or processors.
  246.    * @return Value map
  247.    */
  248.   public @NotNull ValueMap getProperties() {
  249.     if (this.properties == null) {
  250.       this.properties = new ValueMapDecorator(new HashMap<>());
  251.     }
  252.     return this.properties;
  253.   }


  254.   /**
  255.    * Defines a "fallback" property name that is used to load link target information from a single property
  256.    * instead of the link type + link type depending property name. This property is used for migration
  257.    * from components that do not support Link Handler. It is only used for reading, and never written back to.
  258.    * When opened and saved in the link dialog, the property is removed and instead the dedicated properties are used.
  259.    * @param propertyNames Property name(s)
  260.    * @return this
  261.    */
  262.   public @NotNull LinkArgs linkTargetUrlFallbackProperty(@NotNull String @Nullable... propertyNames) {
  263.     this.linkTargetUrlFallbackProperty = propertyNames;
  264.     return this;
  265.   }

  266.   /**
  267.    * @return Property name(s)
  268.    */
  269.   public @Nullable String[] getLinkTargetUrlFallbackProperty() {
  270.     return this.linkTargetUrlFallbackProperty;
  271.   }

  272.   /**
  273.    * Defines a "fallback" property name that is used to load the "windows target" information from
  274.    * instead of the the default property. This property is used for migration
  275.    * from components that do not support Link Handler. It is only used for reading, and never written back to.
  276.    * When opened and saved in the link dialog, the property is removed and instead the dedicated properties are used.
  277.    * @param propertyNames Property name(s)
  278.    * @return this
  279.    */
  280.   public @NotNull LinkArgs linkTargetWindowTargetFallbackProperty(@NotNull String @Nullable... propertyNames) {
  281.     this.linkTargetWindowTargetFallbackProperty = propertyNames;
  282.     return this;
  283.   }

  284.   /**
  285.    * @return Property name(s)
  286.    */
  287.   public @Nullable String[] getLinkTargetWindowTargetFallbackProperty() {
  288.     return this.linkTargetWindowTargetFallbackProperty;
  289.   }


  290.   @Override
  291.   public int hashCode() {
  292.     return HashCodeBuilder.reflectionHashCode(this);
  293.   }

  294.   @Override
  295.   public boolean equals(Object obj) {
  296.     return EqualsBuilder.reflectionEquals(this, obj);
  297.   }

  298.   @Override
  299.   public String toString() {
  300.     return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_OMIT_NULL_STYLE);
  301.   }

  302.   /**
  303.    * Custom clone-method for {@link LinkArgs}
  304.    * @return the cloned {@link LinkArgs}
  305.    */
  306.   @Override
  307.   @SuppressWarnings({ "java:S2975", "java:S1182", "checkstyle:SuperCloneCheck" }) // ignore clone warnings
  308.   public LinkArgs clone() { //NOPMD
  309.     LinkArgs clone = new LinkArgs();

  310.     clone.urlMode = this.urlMode;
  311.     clone.dummyLink = this.dummyLink;
  312.     clone.dummyLinkUrl = this.dummyLinkUrl;
  313.     clone.selectors = this.selectors;
  314.     clone.extension = this.extension;
  315.     clone.suffix = this.suffix;
  316.     clone.queryString = this.queryString;
  317.     clone.fragment = this.fragment;
  318.     clone.windowTarget = this.windowTarget;
  319.     clone.disableSuffixSelector = this.disableSuffixSelector;
  320.     clone.linkTargetUrlFallbackProperty = ArrayUtils.clone(this.linkTargetUrlFallbackProperty);
  321.     clone.linkTargetWindowTargetFallbackProperty = ArrayUtils.clone(this.linkTargetWindowTargetFallbackProperty);
  322.     if (this.properties != null) {
  323.       clone.properties = new ValueMapDecorator(new HashMap<>(this.properties));
  324.     }

  325.     return clone;
  326.   }

  327. }