001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.bean.html5; 018 019import static org.apache.juneau.marshall.xml.XmlFormat.*; 020import static org.apache.juneau.commons.utils.Shorts.*; 021 022import java.util.*; 023 024import org.apache.juneau.commons.bean.*; 025import org.apache.juneau.commons.conversion.*; 026import org.apache.juneau.marshall.*; 027import org.apache.juneau.marshall.xml.*; 028 029/** 030 * A subclass of HTML elements that contain mixed content (elements and text). 031 * 032 * <h5 class='section'>See Also:</h5><ul> 033 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanHtml5">juneau-bean-html5</a> 034 * </ul> 035 * 036 * @param <SELF> The self type for fluent setters. 037 */ 038@SuppressWarnings({ 039 "java:S119" // 'SELF' (CRTP self-type) is intentional and clearer than a single-letter name. 040}) 041public abstract class HtmlElementMixed<SELF extends HtmlElementMixed<SELF>> extends HtmlElement<SELF> { 042 043 private List<Object> children; 044 045 /** 046 * Adds a child element to this element. 047 * 048 * @param value 049 * The child to add as a child element. 050 * Can be a string or {@link HtmlElement}. 051 * Can also be a container of strings and elements. 052 * Can be <jk>null</jk> (a <jk>null</jk> entry is added to the children list). 053 * @return This object. 054 */ 055 public SELF child(Object value) { 056 if (this.children == null) 057 this.children = new LinkedList<>(); 058 if (value instanceof Collection<?> value2) 059 this.children.addAll(value2); 060 else 061 this.children.add(value); 062 return self(); 063 } 064 065 /** 066 * Adds one or more child elements to this element. 067 * 068 * @param value 069 * The children to add as child elements. 070 * Can be a mixture of strings and {@link HtmlElement} objects. 071 * Can also be containers of strings and elements. 072 * Must not be <jk>null</jk>. 073 * @return This object. 074 */ 075 public SELF children(Object...value) { 076 if (value.length != 0) 077 for (var c : value) 078 child(c); 079 return self(); 080 } 081 082 /** 083 * Returns the child node at the specified index. 084 * 085 * @param <T> he class type of the node. 086 * @param type The class type of the node. 087 * @param index The index of the node in the list of children. 088 * @return The child node, or <jk>null</jk> if it doesn't exist. 089 * @throws InvalidConversionException If node is not the expected type. 090 */ 091 public <T> T getChild(Class<T> type, int index) { 092 return (children == null || children.size() <= index || index < 0 ? null : BasicConverter.INSTANCE.to(children.get(index), type)); 093 } 094 095 /** 096 * Returns the child node at the specified index. 097 * 098 * @param index The index of the node in the list of children. 099 * @return The child node, or <jk>null</jk> if it doesn't exist. 100 */ 101 public Object getChild(int index) { 102 return (children == null || children.size() <= index || index < 0 ? null : children.get(index)); 103 } 104 105 /** 106 * Returns the child node at the specified address. 107 * 108 * <p> 109 * Indexes are zero-indexed. 110 * 111 * <p> 112 * For example, calling <c>getChild(1,2,3);</c> will return the 4th child of the 3rd child of the 2nd child. 113 * 114 * @param index The child indexes. 115 * @return The child node, or <jk>null</jk> if it doesn't point to a valid child. 116 */ 117 public Object getChild(int...index) { 118 if (index.length == 0) 119 return null; 120 if (index.length == 1) 121 return getChild(index[0]); 122 Object c = this; 123 for (var element : index) { 124 if (c instanceof HtmlElementMixed<?> c2) 125 c = c2.getChild(element); 126 else if (c instanceof HtmlElementContainer<?> c2) 127 c = c2.getChild(element); 128 else 129 return null; 130 } 131 return c; 132 } 133 134 /** 135 * The children of this element. 136 * 137 * @return The children of this element, or <jk>null</jk> if no children are set. 138 */ 139 @Xml(format = MIXED) 140 @BeanProp(name="c") @MarshalledProp(dictionary=HtmlBeanDictionary.class) 141 public List<Object> getChildren() { return u(children); } 142 143 /** 144 * Sets the children of this element. 145 * 146 * @param children The new children of this element. Can be <jk>null</jk> to clear all children. 147 * @return This object. 148 */ 149 @BeanProp("c") 150 public SELF setChildren(List<Object> children) { 151 this.children = children; 152 return self(); 153 } 154}