001/*
002 * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package org.jdrupes.mdoclet.internal.doclets.formats.html;
027
028import javax.lang.model.element.Element;
029import javax.lang.model.element.ExecutableElement;
030import javax.lang.model.element.TypeElement;
031
032import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.ContentBuilder;
033import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.Entity;
034import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.HtmlStyle;
035import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.HtmlTree;
036import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.Text;
037import org.jdrupes.mdoclet.internal.doclets.toolkit.Content;
038import org.jdrupes.mdoclet.internal.doclets.toolkit.MemberSummaryWriter;
039import org.jdrupes.mdoclet.internal.doclets.toolkit.PropertyWriter;
040
041/**
042 * Writes property documentation in HTML format.
043 */
044public class PropertyWriterImpl extends AbstractMemberWriter
045        implements PropertyWriter, MemberSummaryWriter {
046
047    public PropertyWriterImpl(SubWriterHolderWriter writer,
048            TypeElement typeElement) {
049        super(writer, typeElement);
050    }
051
052    @Override
053    public Content getMemberSummaryHeader(TypeElement typeElement,
054            Content content) {
055        content.add(MarkerComments.START_OF_PROPERTY_SUMMARY);
056        Content memberContent = new ContentBuilder();
057        writer.addSummaryHeader(this, memberContent);
058        return memberContent;
059    }
060
061    @Override
062    public void addSummary(Content summariesList, Content content) {
063        writer.addSummary(HtmlStyle.propertySummary,
064            HtmlIds.PROPERTY_SUMMARY, summariesList, content);
065    }
066
067    @Override
068    public Content getPropertyDetailsHeader(Content memberDetails) {
069        memberDetails.add(MarkerComments.START_OF_PROPERTY_DETAILS);
070        Content propertyDetailsContent = new ContentBuilder();
071        var heading = HtmlTree.HEADING(Headings.TypeDeclaration.DETAILS_HEADING,
072            contents.propertyDetailsLabel);
073        propertyDetailsContent.add(heading);
074        return propertyDetailsContent;
075    }
076
077    @Override
078    public Content getPropertyHeaderContent(ExecutableElement property) {
079        Content content = new ContentBuilder();
080        var heading = HtmlTree.HEADING(Headings.TypeDeclaration.MEMBER_HEADING,
081            Text.of(utils.getPropertyLabel(name(property))));
082        content.add(heading);
083        return HtmlTree.SECTION(HtmlStyle.detail, content)
084            .setId(htmlIds.forProperty(property));
085    }
086
087    @Override
088    public Content getSignature(ExecutableElement property) {
089        return new Signatures.MemberSignature(property, this)
090            .setType(utils.getReturnType(typeElement, property))
091            .setAnnotations(writer.getAnnotationInfo(property, true))
092            .toContent();
093    }
094
095    @Override
096    public void addDeprecated(ExecutableElement property,
097            Content propertyContent) {
098    }
099
100    @Override
101    public void addPreview(ExecutableElement property, Content content) {
102    }
103
104    @Override
105    public void addComments(ExecutableElement property,
106            Content propertyContent) {
107        TypeElement holder = (TypeElement) property.getEnclosingElement();
108        if (!utils.getFullBody(property).isEmpty()) {
109            if (holder.equals(typeElement) ||
110                (!utils.isPublic(holder) || utils.isLinkable(holder))) {
111                writer.addInlineComment(property, propertyContent);
112            } else {
113                if (!utils.hasHiddenTag(holder)
114                    && !utils.hasHiddenTag(property)) {
115                    Content link = writer.getDocLink(HtmlLinkInfo.Kind.PLAIN,
116                        holder, property,
117                        utils.isIncluded(holder)
118                            ? holder.getSimpleName()
119                            : holder.getQualifiedName());
120                    var codeLink = HtmlTree.CODE(link);
121                    var descriptionFromLabel
122                        = HtmlTree.SPAN(HtmlStyle.descriptionFromTypeLabel,
123                            utils.isClass(holder)
124                                ? contents.descriptionFromClassLabel
125                                : contents.descriptionFromInterfaceLabel);
126                    descriptionFromLabel.add(Entity.NO_BREAK_SPACE);
127                    descriptionFromLabel.add(codeLink);
128                    propertyContent.add(
129                        HtmlTree.DIV(HtmlStyle.block, descriptionFromLabel));
130                }
131                writer.addInlineComment(property, propertyContent);
132            }
133        }
134    }
135
136    @Override
137    public void addTags(ExecutableElement property, Content propertyContent) {
138        writer.addTagsInfo(property, propertyContent);
139    }
140
141    @Override
142    public Content getPropertyDetails(Content memberDetailsHeader,
143            Content memberDetails) {
144        return writer.getDetailsListItem(
145            HtmlTree.SECTION(HtmlStyle.propertyDetails)
146                .setId(HtmlIds.PROPERTY_DETAIL)
147                .add(memberDetailsHeader)
148                .add(memberDetails));
149    }
150
151    @Override
152    public void addSummaryLabel(Content content) {
153        var label = HtmlTree.HEADING(Headings.TypeDeclaration.SUMMARY_HEADING,
154            contents.propertySummaryLabel);
155        content.add(label);
156    }
157
158    @Override
159    public TableHeader getSummaryTableHeader(Element member) {
160        return new TableHeader(contents.typeLabel, contents.propertyLabel,
161            contents.descriptionLabel);
162    }
163
164    @Override
165    protected Table<Element> createSummaryTable() {
166        return new Table<Element>(HtmlStyle.summaryTable)
167            .setCaption(contents.properties)
168            .setHeader(getSummaryTableHeader(typeElement))
169            .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond,
170                HtmlStyle.colLast);
171    }
172
173    @Override
174    public void addInheritedSummaryLabel(TypeElement typeElement,
175            Content content) {
176        Content classLink = writer.getPreQualifiedClassLink(
177            HtmlLinkInfo.Kind.PLAIN, typeElement);
178        Content label;
179        if (options.summarizeOverriddenMethods()) {
180            label = Text.of(utils.isClass(typeElement)
181                ? resources.getText("doclet.Properties_Declared_In_Class")
182                : resources.getText("doclet.Properties_Declared_In_Interface"));
183        } else {
184            label = Text.of(utils.isClass(typeElement)
185                ? resources.getText("doclet.Properties_Inherited_From_Class")
186                : resources
187                    .getText("doclet.Properties_Inherited_From_Interface"));
188        }
189        var labelHeading = HtmlTree
190            .HEADING(Headings.TypeDeclaration.INHERITED_SUMMARY_HEADING, label)
191            .setId(htmlIds.forInheritedProperties(typeElement))
192            .add(Entity.NO_BREAK_SPACE)
193            .add(classLink);
194        content.add(labelHeading);
195    }
196
197    @Override
198    protected void addSummaryLink(HtmlLinkInfo.Kind context,
199            TypeElement typeElement, Element member,
200            Content content) {
201        Content memberLink = writer.getDocLink(context, typeElement,
202            member,
203            Text.of(utils.getPropertyLabel(name(member))),
204            HtmlStyle.memberNameLink,
205            true);
206
207        var code = HtmlTree.CODE(memberLink);
208        content.add(code);
209    }
210
211    @Override
212    protected void addInheritedSummaryLink(TypeElement typeElement,
213            Element member, Content target) {
214        String mname = name(member);
215        Content content
216            = writer.getDocLink(HtmlLinkInfo.Kind.PLAIN, typeElement, member,
217                utils.isProperty(mname) ? utils.getPropertyName(mname) : mname,
218                true);
219        target.add(content);
220    }
221
222    @Override
223    protected void addSummaryType(Element member, Content content) {
224        addModifiersAndType(member,
225            utils.getReturnType(typeElement, (ExecutableElement) member),
226            content);
227    }
228
229    @Override
230    protected Content getSummaryLink(Element member) {
231        return writer.getDocLink(HtmlLinkInfo.Kind.SHOW_PREVIEW, member,
232            utils.getFullyQualifiedName(member));
233    }
234
235}