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

com.helger.html.meta.MetaElement Maven / Gradle / Ivy

/**
 * Copyright (C) 2014-2016 Philip Helger (www.helger.com)
 * philip[at]helger[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.helger.html.meta;

import java.util.Locale;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import javax.xml.XMLConstants;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.helger.commons.CGlobal;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.annotation.OverrideOnDemand;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.collection.ext.CommonsArrayList;
import com.helger.commons.collection.ext.CommonsLinkedHashMap;
import com.helger.commons.collection.ext.ICommonsList;
import com.helger.commons.collection.ext.ICommonsOrderedMap;
import com.helger.commons.collection.ext.ICommonsOrderedSet;
import com.helger.commons.equals.EqualsHelper;
import com.helger.commons.hashcode.HashCodeGenerator;
import com.helger.commons.locale.LocaleHelper;
import com.helger.commons.state.EChange;
import com.helger.commons.string.StringHelper;
import com.helger.commons.string.ToStringGenerator;
import com.helger.html.CHTMLAttributes;
import com.helger.html.EHTMLElement;
import com.helger.html.hc.IHCConversionSettingsToNode;
import com.helger.xml.microdom.IMicroContainer;
import com.helger.xml.microdom.IMicroElement;
import com.helger.xml.microdom.IMicroNode;
import com.helger.xml.microdom.MicroContainer;

/**
 * Represents a single HTML meta element.
 *
 * @author Philip Helger
 */
@NotThreadSafe
public class MetaElement implements IMutableMetaElement
{
  /** By default the meta element is not an HTTP equivalent */
  public static final boolean DEFAULT_IS_HTTP_EQUIV = false;

  private static final Logger s_aLogger = LoggerFactory.getLogger (MetaElement.class);
  /** tag name. */
  private final String m_sName;

  /** optional scheme string. */
  private String m_sScheme;

  /** HTTP equivalent or not? */
  private boolean m_bIsHttpEquiv;

  /** locale to value map. */
  private final ICommonsOrderedMap  m_aContents = new CommonsLinkedHashMap <> ();

  public MetaElement (@Nonnull final IMetaElementDeclaration aMetaTagDecl, @Nullable final String sContent)
  {
    this (aMetaTagDecl.getName (), aMetaTagDecl.isHttpEquiv (), (Locale) null, sContent);
    setScheme (aMetaTagDecl.getScheme ());
  }

  public MetaElement (@Nonnull final String sName, @Nullable final String sContent)
  {
    this (sName, DEFAULT_IS_HTTP_EQUIV, (Locale) null, sContent);
  }

  public MetaElement (@Nonnull final String sName, final boolean bIsHttpEquiv, @Nullable final String sContent)
  {
    this (sName, bIsHttpEquiv, (Locale) null, sContent);
  }

  public MetaElement (@Nonnull final String sName,
                      final boolean bIsHttpEquiv,
                      @Nullable final Locale aContentLocale,
                      @Nullable final String sContent)
  {
    m_sName = ValueEnforcer.notNull (sName, "Name");
    setHttpEquiv (bIsHttpEquiv);
    setContent (aContentLocale, sContent);
  }

  @Nonnull
  public String getName ()
  {
    return m_sName;
  }

  @Nullable
  public String getScheme ()
  {
    return m_sScheme;
  }

  @Nonnull
  public EChange setScheme (@Nullable final String sScheme)
  {
    if (EqualsHelper.equals (sScheme, m_sScheme))
      return EChange.UNCHANGED;
    m_sScheme = sScheme;
    return EChange.CHANGED;
  }

  public boolean isHttpEquiv ()
  {
    return m_bIsHttpEquiv;
  }

  @Nonnull
  public EChange setHttpEquiv (final boolean bIsHttpEquiv)
  {
    if (m_bIsHttpEquiv == bIsHttpEquiv)
      return EChange.UNCHANGED;
    m_bIsHttpEquiv = bIsHttpEquiv;
    return EChange.CHANGED;
  }

  public boolean isLanguageIndependent ()
  {
    return m_aContents.containsKey (CGlobal.LOCALE_INDEPENDENT);
  }

  @Nonnull
  @ReturnsMutableCopy
  public ICommonsOrderedSet  getAllLocales ()
  {
    return m_aContents.copyOfKeySet ();
  }

  @Nullable
  public String getContentLanguageIndependent ()
  {
    return m_aContents.get (CGlobal.LOCALE_INDEPENDENT);
  }

  @Nonnull
  @ReturnsMutableCopy
  public ICommonsOrderedMap  getContent ()
  {
    return m_aContents.getClone ();
  }

  @Nonnull
  public static Locale getRealContentLocale (@Nullable final Locale aContentLocale)
  {
    return aContentLocale == null ? CGlobal.LOCALE_INDEPENDENT : aContentLocale;
  }

  @Nonnull
  public EChange setContent (@Nullable final String sContent)
  {
    return setContent ((Locale) null, sContent);
  }

  @Nonnull
  public EChange setContent (@Nullable final Locale aContentLocale, @Nullable final String sContent)
  {
    final Locale aRealContentLocale = getRealContentLocale (aContentLocale);
    final String sOldContent = m_aContents.get (aRealContentLocale);
    if (EqualsHelper.equals (sOldContent, sContent))
      return EChange.UNCHANGED;

    if (sContent == null)
      m_aContents.remove (aRealContentLocale);
    else
      m_aContents.put (aRealContentLocale, sContent);
    return EChange.CHANGED;
  }

  @Nonnull
  public EChange removeContent ()
  {
    return removeContent ((Locale) null);
  }

  @Nonnull
  public EChange removeContent (@Nullable final Locale aContentLocale)
  {
    final Locale aRealContentLocale = getRealContentLocale (aContentLocale);
    // Manually check for key, as the value can be null
    if (!m_aContents.containsKey (aRealContentLocale))
      return EChange.UNCHANGED;

    m_aContents.remove (aRealContentLocale);
    return EChange.CHANGED;
  }

  @Nonnull
  @ReturnsMutableCopy
  public ICommonsList  getAsMetaElementValueList ()
  {
    final ICommonsList  ret = new CommonsArrayList <> (m_aContents.size ());
    for (final Map.Entry  aEntry : m_aContents.entrySet ())
      ret.add (new MetaElementValue (m_sName, aEntry.getKey (), aEntry.getValue (), m_bIsHttpEquiv));
    return ret;
  }

  @Nonnull
  @Nonempty
  @OverrideOnDemand
  protected String getNamespaceURI (@Nonnull final IHCConversionSettingsToNode aConversionSettings)
  {
    return aConversionSettings.getHTMLNamespaceURI ();
  }

  /**
   * @return The attribute name that contains the meta element name. May neither
   *         be null nor empty
   */
  @Nonnull
  @Nonempty
  @OverrideOnDemand
  protected String getNodeNameAttribute ()
  {
    return CHTMLAttributes.NAME;
  }

  /**
   * @return The attribute name that contains the meta element content. May
   *         neither be null nor empty
   */
  @Nonnull
  @Nonempty
  @OverrideOnDemand
  protected String getNodeContentAttribute ()
  {
    return CHTMLAttributes.CONTENT;
  }

  @Nullable
  public IMicroNode convertToNode (@Nonnull final IHCConversionSettingsToNode aConversionSettings)
  {
    if (m_aContents.isEmpty ())
    {
      s_aLogger.info ("Meta element '" + m_sName + "' has no content!");
      return null;
    }

    final String sNamespaceURI = getNamespaceURI (aConversionSettings);
    final boolean bAtLeastHTML5 = aConversionSettings.getHTMLVersion ().isAtLeastHTML5 ();

    // determine whether the key is an "http-equiv" or a "name" or a
    // "property"
    final boolean bIsHttpEquiv = m_bIsHttpEquiv || EStandardMetaElement.isHttpEquivMetaElement (m_sName);

    final IMicroContainer ret = new MicroContainer ();
    for (final Map.Entry  aMetaEntry : m_aContents.entrySet ())
    {
      final IMicroElement aMeta = ret.appendElement (sNamespaceURI, EHTMLElement.META.getElementName ());
      aMeta.setAttribute (bIsHttpEquiv ? CHTMLAttributes.HTTP_EQUIV : getNodeNameAttribute (), m_sName);
      aMeta.setAttribute (getNodeContentAttribute (), aMetaEntry.getValue ());
      final Locale aContentLocale = aMetaEntry.getKey ();
      if (aContentLocale != null && !LocaleHelper.isSpecialLocale (aContentLocale))
      {
        final String sLang = aContentLocale.toString ();
        aMeta.setAttribute (XMLConstants.XML_NS_URI, CHTMLAttributes.LANG, sLang);
        if (bAtLeastHTML5)
        {
          // When the attribute xml:lang in no namespace is specified, the
          // element must also have the attribute lang present with the same
          // value
          aMeta.setAttribute (CHTMLAttributes.LANG, sLang);
        }
      }

      // No scheme attr in HTML5
      if (!bAtLeastHTML5 && StringHelper.hasText (m_sScheme))
        aMeta.setAttribute (CHTMLAttributes.SCHEME, m_sScheme);
    }
    return ret;
  }

  @Override
  public boolean equals (final Object o)
  {
    if (o == this)
      return true;
    if (o == null || !getClass ().equals (o.getClass ()))
      return false;
    final MetaElement rhs = (MetaElement) o;
    return m_sName.equals (rhs.m_sName) &&
           EqualsHelper.equals (m_sScheme, rhs.m_sScheme) &&
           m_aContents.equals (rhs.m_aContents) &&
           m_bIsHttpEquiv == rhs.m_bIsHttpEquiv;
  }

  @Override
  public int hashCode ()
  {
    return new HashCodeGenerator (this).append (m_sName)
                                       .append (m_sScheme)
                                       .append (m_aContents)
                                       .append (m_bIsHttpEquiv)
                                       .getHashCode ();
  }

  @Override
  public String toString ()
  {
    return new ToStringGenerator (this).append ("name", m_sName)
                                       .appendIfNotNull ("scheme", m_sScheme)
                                       .append ("contents", m_aContents)
                                       .append ("isHttpEquiv", m_bIsHttpEquiv)
                                       .toString ();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy