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.html; 014 015import org.apache.juneau.html.annotation.*; 016import org.apache.juneau.serializer.*; 017 018/** 019 * Allows custom rendering of bean property values when serialized as HTML. 020 * 021 * <p> 022 * Associated with bean properties using the {@link Html#render() @Html.render()} annotation. 023 * 024 * <p> 025 * Using this class, you can alter the CSS style and HTML content of the bean property. 026 * 027 * <p> 028 * The following example shows two render classes that customize the appearance of the <code>pctFull</code> and 029 * <code>status</code> columns shown below: 030 * 031 * <p> 032 * <img class='bordered' src='doc-files/HtmlRender_1.png'> 033 * 034 * <p class='bcode'> 035 * <jc>// Our bean class</jc> 036 * <jk>public class</jk> FileSpace { 037 * 038 * <jk>private final</jk> String <jf>drive</jf>; 039 * <jk>private final long</jk> <jf>total</jf>, <jf>available</jf>; 040 * 041 * <jk>public</jk> FileSpace(String drive, <jk>long</jk> total, <jk>long</jk> available) { 042 * <jk>this</jk>.<jf>drive</jf> = drive; 043 * <jk>this</jk>.<jf>total</jf> = total; 044 * <jk>this</jk>.<jf>available</jf> = available; 045 * } 046 * 047 * <ja>@Html</ja>(link=<js>"drive/{drive}"</js>) 048 * <jk>public</jk> String getDrive() { 049 * <jk>return</jk> <jf>drive</jf>; 050 * } 051 * 052 * <jk>public long</jk> getTotal() { 053 * <jk>return</jk> <jf>total</jf>; 054 * } 055 * 056 * <jk>public long</jk> getAvailable() { 057 * <jk>return</jk> <jf>available</jf>; 058 * } 059 * 060 * <ja>@Html</ja>(render=FileSpacePctRender.<jk>class</jk>) 061 * <jk>public float</jk> getPctFull() { 062 * <jk>return</jk> ((100 * <jf>available</jf>) / <jf>total</jf>); 063 * } 064 * 065 * <ja>@Html</ja>(render=FileSpaceStatusRender.<jk>class</jk>) 066 * <jk>public</jk> FileSpaceStatus getStatus() { 067 * <jk>float</jk> pf = getPctFull(); 068 * <jk>if</jk> (pf < 80) 069 * <jk>return</jk> FileSpaceStatus.<jsf>OK</jsf>; 070 * <jk>if</jk> (pf < 90) 071 * <jk>return</jk> FileSpaceStatus.<jsf>WARNING</jsf>; 072 * <jk>return</jk> FileSpaceStatus.<jsf>SEVERE</jsf>; 073 * } 074 * } 075 * 076 * <jc>// Possible values for the getStatus() method</jc> 077 * <jk>public static enum</jk> FileSpaceStatus { 078 * <jsf>OK</jsf>, <jsf>WARNING</jsf>, <jsf>SEVERE</jsf>; 079 * } 080 * 081 * <jc>// Custom render for getPctFull() method</jc> 082 * <jk>public static class</jk> FileSpacePctRender <jk>extends</jk> HtmlRender<Float> { 083 * 084 * <ja>@Override</ja> 085 * <jk>public</jk> String getStyle(SerializerSession session, Float value) { 086 * <jk>if</jk> (value < 80) 087 * <jk>return</jk> <js>"background-color:lightgreen;text-align:center"</js>; 088 * <jk>if</jk> (value < 90) 089 * <jk>return</jk> <js>"background-color:yellow;text-align:center"</js>; 090 * <jk>return</jk> <js>"background-color:red;text-align:center;border:;animation:color_change 0.5s infinite alternate"</js>; 091 * } 092 * 093 * <ja>@Override</ja> 094 * <jk>public</jk> Object getContent(SerializerSession session, Float value) { 095 * <jk>if</jk> (value >= 90) 096 * <jk>return</jk> <jsm>div</jsm>( 097 * String.<jsm>format</jsm>(<js>"%.0f%%"</js>, value), 098 * <jsm>style</jsm>(<js>"@keyframes color_change { from { background-color: red; } to { background-color: yellow; }"</js>) 099 * ); 100 * <jk>return</jk> String.<jsm>format</jsm>(<js>"%.0f%%"</js>, value); 101 * } 102 * } 103 * 104 * <jc>// Custom render for getStatus() method</jc> 105 * <jk>public static class</jk> FileSpaceStatusRender <jk>extends</jk> HtmlRender<FileSpaceStatus> { 106 * 107 * <ja>@Override</ja> 108 * <jk>public</jk> String getStyle(SerializerSession session, FileSpaceStatus value) { 109 * <jk>return</jk> <js>"text-align:center"</js>; 110 * } 111 * 112 * <ja>@Override</ja> 113 * <jk>public</jk> Object getContent(SerializerSession session, FileSpaceStatus value) { 114 * <jk>switch</jk> (value) { 115 * <jk>case</jk> <jsf>OK</jsf>: <jk>return</jk> <jsm>img</jsm>().src(URI.<jsm>create</jsm>(<js>"servlet:/htdocs/ok.png"</js>)); 116 * <jk>case</jk> <jsf>WARNING</jsf>: <jk>return</jk> <jsm>img</jsm>().src(URI.<jsm>create</jsm>(<js>"servlet:/htdocs/warning.png"</js>)); 117 * <jk>default</jk>: <jk>return</jk> <jsm>img</jsm>().src(URI.<jsm>create</jsm>(<js>"servlet:/htdocs/severe.png"</js>)); 118 * } 119 * } 120 * } 121 * </p> 122 * 123 * @param <T> The bean property type. 124 */ 125public abstract class HtmlRender<T> { 126 127 /** 128 * Returns the CSS style of the element containing the bean property value. 129 * 130 * @param session 131 * The current serializer session. 132 * Can be used to retrieve properties and session-level information. 133 * @param value The bean property value. 134 * @return The CSS style string, or <jk>null</jk> if no style should be added. 135 */ 136 public String getStyle(SerializerSession session, T value) { 137 return null; 138 } 139 140 /** 141 * Returns the delegate value for the specified bean property value. 142 * 143 * <p> 144 * The default implementation simply returns the same value. 145 * A typical use is to return an HTML element using one of the HTML5 DOM beans. 146 * 147 * @param session 148 * The current serializer session. 149 * Can be used to retrieve properties and session-level information. 150 * @param value The bean property value. 151 * @return The new bean property value. 152 */ 153 public Object getContent(SerializerSession session, T value) { 154 return value; 155 } 156}