All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.phloc.web.sitemap.XMLSitemapURL Maven / Gradle / Ivy

/**
 * Copyright (C) 2006-2015 phloc systems
 * http://www.phloc.com
 * office[at]phloc[dot]com
 *
 * 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.
 */
package com.phloc.web.sitemap;

import java.io.Serializable;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import org.joda.time.DateTime;

import com.phloc.commons.ValueEnforcer;
import com.phloc.commons.equals.EqualsUtils;
import com.phloc.commons.hash.HashCodeGenerator;
import com.phloc.commons.microdom.IMicroElement;
import com.phloc.commons.microdom.impl.MicroElement;
import com.phloc.commons.string.ToStringGenerator;
import com.phloc.commons.url.ISimpleURL;
import com.phloc.commons.xml.EXMLCharMode;
import com.phloc.commons.xml.serialize.XMLMaskHelper;
import com.phloc.datetime.IHasLastModificationDateTime;
import com.phloc.datetime.PDTUtils;
import com.phloc.web.datetime.PDTWebDateUtils;

/**
 * Represents a single URL within an XML URL set.
 * 
 * @author Philip Helger
 */
@Immutable
public final class XMLSitemapURL implements IHasLastModificationDateTime, Serializable
{
  /** Maximum length of a single URL */
  public static final int LOCATION_MAX_LENGTH = 2048;
  public static final double MIN_PRIORITY = 0;
  public static final double MAX_PRIORITY = 1;
  public static final double DEFAULT_PRIORITY = 0.5;

  private static final String ELEMENT_URL = "url";
  private static final String ELEMENT_LOC = "loc";
  private static final String ELEMENT_LASTMOD = "lastmod";
  private static final String ELEMENT_CHANGEFREQ = "changefreq";
  private static final String ELEMENT_PRIORITY = "priority";

  private final String m_sLocation;
  private final DateTime m_aLastModification;
  private final EXMLSitemapChangeFequency m_eChangeFreq;
  private final double m_dPriority;
  private final String m_sPriority;
  private final int m_nOutputLength;

  public XMLSitemapURL (@Nonnull final ISimpleURL aLocation)
  {
    this (aLocation, null);
  }

  public XMLSitemapURL (@Nonnull final ISimpleURL aLocation, @Nullable final DateTime aLastModification)
  {
    this (aLocation, aLastModification, null, null);
  }

  public XMLSitemapURL (@Nonnull final ISimpleURL aLocation,
                        @Nullable final DateTime aLastModification,
                        @Nullable final EXMLSitemapChangeFequency eChangeFreq,
                        @Nullable final Double aPriority)
  {
    ValueEnforcer.notNull (aLocation, "Location");
    if (aPriority != null)
      ValueEnforcer.isBetweenInclusive (aPriority.doubleValue (), "Priority", MIN_PRIORITY, MAX_PRIORITY);

    m_sLocation = aLocation.getAsString ();
    if (m_sLocation.length () > LOCATION_MAX_LENGTH)
      throw new IllegalArgumentException ("URL location is too long!");
    m_aLastModification = PDTUtils.isNullValue (aLastModification) ? null : aLastModification;
    m_eChangeFreq = eChangeFreq;
    m_dPriority = aPriority == null ? DEFAULT_PRIORITY : aPriority.doubleValue ();
    m_sPriority = aPriority == null ? null : aPriority.toString ();
    m_nOutputLength = _buildEstimatedOutputLength ();
  }

  /**
   * Get the length of a single tag name in XML representation for open AND
   * close together.
   * 
   * @param s
   *        The tag name without leading and trailing angle brackets
   * @return The length in chars in XML representation
   */
  @Nonnegative
  private static int _getTagOutputLength (@Nonnull final String s)
  {
    // length + "<" + ">" + "<" + "/>"
    return s.length () * 2 + 5;
  }

  @Nonnegative
  private int _buildEstimatedOutputLength ()
  {
    //  element
    int ret = _getTagOutputLength (ELEMENT_URL);

    // 
    ret += _getTagOutputLength (ELEMENT_LOC) +
           XMLMaskHelper.getMaskedXMLTextLength (CXMLSitemap.XML_WRITER_SETTINGS.getXMLVersion (),
                                                 EXMLCharMode.TEXT,
                                                 CXMLSitemap.XML_WRITER_SETTINGS.getIncorrectCharacterHandling (),
                                                 m_sLocation);

    if (m_aLastModification != null)
    {
      // 24 == length of formatted date
      ret += _getTagOutputLength (ELEMENT_LASTMOD) + 24;
    }

    if (m_eChangeFreq != null)
      ret += _getTagOutputLength (ELEMENT_CHANGEFREQ) + m_eChangeFreq.getText ().length ();

    if (m_sPriority != null)
      ret += _getTagOutputLength (ELEMENT_PRIORITY) + m_sPriority.length ();

    return ret;
  }

  @Nonnull
  public String getLocation ()
  {
    return m_sLocation;
  }

  @Nullable
  public DateTime getLastModificationDateTime ()
  {
    return m_aLastModification;
  }

  @Nullable
  public EXMLSitemapChangeFequency getChangeFrequency ()
  {
    return m_eChangeFreq;
  }

  @Nonnegative
  public double getPriority ()
  {
    return m_dPriority;
  }

  @Nullable
  public String getPriorityString ()
  {
    return m_sPriority;
  }

  @Nonnegative
  public int getOutputLength ()
  {
    return m_nOutputLength;
  }

  @Nonnull
  public IMicroElement getAsElement ()
  {
    final String sNamespaceURI = CXMLSitemap.XML_NAMESPACE_0_9;
    final IMicroElement ret = new MicroElement (sNamespaceURI, ELEMENT_URL);
    ret.appendElement (sNamespaceURI, ELEMENT_LOC).appendText (m_sLocation);
    if (m_aLastModification != null)
      ret.appendElement (sNamespaceURI, ELEMENT_LASTMOD)
         .appendText (PDTWebDateUtils.getAsStringXSD (m_aLastModification));
    if (m_eChangeFreq != null)
      ret.appendElement (sNamespaceURI, ELEMENT_CHANGEFREQ).appendText (m_eChangeFreq.getText ());
    if (m_sPriority != null)
      ret.appendElement (sNamespaceURI, ELEMENT_PRIORITY).appendText (m_sPriority);
    return ret;
  }

  @Override
  public boolean equals (final Object o)
  {
    if (o == this)
      return true;
    if (!(o instanceof XMLSitemapURL))
      return false;
    final XMLSitemapURL rhs = (XMLSitemapURL) o;
    // Don't compare output length and double priority as they are calculated
    return m_sLocation.equals (rhs.m_sLocation) &&
           EqualsUtils.equals (m_aLastModification, rhs.m_aLastModification) &&
           EqualsUtils.equals (m_eChangeFreq, rhs.m_eChangeFreq) &&
           EqualsUtils.equals (m_sPriority, rhs.m_sPriority);
  }

  @Override
  public int hashCode ()
  {
    // Don't compare output length and double priority as they are calculated
    return new HashCodeGenerator (this).append (m_sLocation)
                                       .append (m_aLastModification)
                                       .append (m_eChangeFreq)
                                       .append (m_sPriority)
                                       .getHashCode ();
  }

  @Override
  public String toString ()
  {
    return new ToStringGenerator (this).append ("location", m_sLocation)
                                       .appendIfNotNull ("lastModification", m_aLastModification)
                                       .appendIfNotNull ("changeFrequency", m_eChangeFreq)
                                       .appendIfNotNull ("priority", m_sPriority)
                                       .append ("outputLength", m_nOutputLength)
                                       .toString ();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy