001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.dto.html5;
014
015import static org.apache.juneau.xml.annotation.XmlFormat.*;
016
017import java.util.*;
018
019import org.apache.juneau.*;
020import org.apache.juneau.annotation.*;
021import org.apache.juneau.internal.*;
022import org.apache.juneau.xml.annotation.*;
023
024/**
025 * A subclass of HTML elements that contain only other elements, not text.
026 *
027 * <ul class='seealso'>
028 *    <li class='link'>{@doc juneau-dto.HTML5}
029 * </ul>
030 */
031public class HtmlElementContainer extends HtmlElement {
032
033   private LinkedList<Object> children;
034
035   /**
036    * The children of this element.
037    *
038    * @return The children of this element.
039    */
040   @Xml(format=ELEMENTS)
041   @BeanProperty(beanDictionary=HtmlBeanDictionary.class, name="c")
042   public LinkedList<Object> getChildren() {
043      return children;
044   }
045
046   /**
047    * Sets the children for this container.
048    *
049    * @param children The new children for this container.
050    * @return This object (for method chaining).
051    */
052   @BeanProperty("c")
053   public HtmlElementContainer setChildren(LinkedList<Object> children) {
054      this.children = children;
055      return this;
056   }
057
058   /**
059    * Returns the child node at the specified index.
060    *
061    * @param index The index of the node in the list of children.
062    * @return The child node, or <jk>null</jk> if it doesn't exist.
063    */
064   public Object getChild(int index) {
065      return (children == null || children.size() <= index || index < 0 ? null : children.get(index));
066   }
067
068   /**
069    * Returns the child node at the specified address.
070    *
071    * <p>
072    * Indexes are zero-indexed.
073    *
074    * <p>
075    * For example, calling <c>getChild(1,2,3);</c> will return the 4th child of the 3rd child of the 2nd child.
076    *
077    * @param index The child indexes.
078    * @return The child node, or <jk>null</jk> if it doesn't point to a valid child.
079    */
080   public Object getChild(int...index) {
081      if (index.length == 0)
082         return null;
083      if (index.length == 1)
084         return getChild(index[0]);
085      Object c = this;
086      for (int i = 0; i < index.length; i++) {
087         if (c instanceof HtmlElementMixed)
088            c = ((HtmlElementMixed)c).getChild(index[i]);
089         else if (c instanceof HtmlElementContainer)
090            c = ((HtmlElementContainer)c).getChild(index[i]);
091         else
092            return null;
093      }
094      return c;
095   }
096
097   /**
098    * Returns the child node at the specified index.
099    *
100    * @param type The class type of the node.
101    * @param index The index of the node in the list of children.
102    * @return The child node, or <jk>null</jk> if it doesn't exist.
103    * @throws InvalidDataConversionException If node is not the expected type.
104    */
105   public <T> T getChild(Class<T> type, int index) {
106      return (children == null || children.size() <= index || index < 0
107         ? null
108         : ObjectUtils.toType(children.get(index), type)
109      );
110   }
111
112   /**
113    * Adds one or more child elements to this element.
114    *
115    * @param children The children to add as child elements.
116    * @return This object (for method chaining).
117    */
118   public HtmlElement children(Object...children) {
119      if (children.length > 0) {
120         if (this.children == null)
121            this.children = new LinkedList<>();
122         for (Object c : children)
123            this.children.add(c);
124      }
125      return this;
126   }
127
128   /**
129    * Adds a child element to this element.
130    *
131    * @param child The child to add as a child element.
132    * @return This object (for method chaining).
133    */
134   public HtmlElement child(Object child) {
135      if (this.children == null)
136         this.children = new LinkedList<>();
137      this.children.add(child);
138      return this;
139   }
140}