001package ball.tools.javadoc; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: IncludeTaglet.java 6035 2020-05-25 03:01:46Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/tools/javadoc/IncludeTaglet.java $ 007 * %% 008 * Copyright (C) 2008 - 2020 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import ball.annotation.ServiceProviderFor; 024import ball.swing.table.ListTableModel; 025import ball.swing.table.MapTableModel; 026import ball.xml.FluentNode; 027import com.sun.javadoc.ClassDoc; 028import com.sun.javadoc.Tag; 029import com.sun.tools.doclets.Taglet; 030import java.io.InputStream; 031import java.util.Collection; 032import java.util.Map; 033import java.util.regex.Pattern; 034import java.util.stream.Collectors; 035import lombok.NoArgsConstructor; 036import lombok.ToString; 037import org.apache.commons.io.IOUtils; 038 039import static org.apache.commons.lang3.StringUtils.isNotEmpty; 040 041/** 042 * Inline {@link Taglet} to include a static {@link Class} 043 * {@link java.lang.reflect.Field} or resource in the Javadoc output. 044 * 045 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 046 * @version $Revision: 6035 $ 047 */ 048@ServiceProviderFor({ Taglet.class }) 049@TagletName("include") 050@NoArgsConstructor @ToString 051public class IncludeTaglet extends AbstractInlineTaglet 052 implements SunToolsInternalToolkitTaglet { 053 private static final IncludeTaglet INSTANCE = new IncludeTaglet(); 054 055 public static void register(Map<Object,Object> map) { 056 register(map, INSTANCE); 057 } 058 059 @Override 060 public FluentNode toNode(Tag tag) throws Throwable { 061 FluentNode node = null; 062 String[] text = tag.text().trim().split(Pattern.quote("#"), 2); 063 064 if (text.length > 1) { 065 node = 066 field(tag, 067 getClassFor(isNotEmpty(text[0]) 068 ? getClassDocFor(tag, text[0]) 069 : containingClass(tag)), 070 text[1]); 071 } else { 072 node = 073 resource(tag, 074 getClassFor(containingClass(tag)), 075 text[0]); 076 } 077 078 return node; 079 } 080 081 private FluentNode field(Tag tag, 082 Class<?> type, String name) throws Exception { 083 Object object = type.getField(name).get(null); 084 FluentNode node = null; 085 086 if (object instanceof Collection<?>) { 087 node = 088 table(tag, 089 new ListTableModel(((Collection<?>) object) 090 .stream() 091 .collect(Collectors.toList()), 092 "Element")); 093 } else if (object instanceof Map<?,?>) { 094 node = 095 table(tag, 096 new MapTableModel((Map<?,?>) object, "Key", "Value")); 097 } else { 098 node = pre(String.valueOf(object)); 099 } 100 101 return div(attr("class", "block"), node); 102 } 103 104 private FluentNode resource(Tag tag, 105 Class<?> type, String name) throws Exception { 106 String string = null; 107 108 if (type == null) { 109 type = getClass(); 110 } 111 112 try (InputStream in = type.getResourceAsStream(name)) { 113 string = IOUtils.toString(in, "UTF-8"); 114 } 115 116 return pre(string); 117 } 118}