001package org.apache.maven.tools.plugin.generator;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import static java.nio.charset.StandardCharsets.UTF_8;
023
024import org.apache.maven.plugin.descriptor.MojoDescriptor;
025import org.apache.maven.plugin.descriptor.Parameter;
026import org.apache.maven.project.MavenProject;
027import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
028import org.apache.maven.tools.plugin.PluginToolsRequest;
029import org.codehaus.plexus.util.StringUtils;
030import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
031import org.codehaus.plexus.util.xml.XMLWriter;
032
033import java.io.File;
034import java.io.FileOutputStream;
035import java.io.IOException;
036import java.io.OutputStreamWriter;
037import java.io.PrintWriter;
038import java.io.Writer;
039import java.text.MessageFormat;
040import java.util.ArrayList;
041import java.util.Iterator;
042import java.util.List;
043import java.util.Locale;
044import java.util.ResourceBundle;
045
046/**
047 * Generate xdoc documentation for each mojo.
048 */
049public class PluginXdocGenerator
050    implements Generator
051{
052    /**
053     * locale
054     */
055    private final Locale locale;
056
057    /**
058     * project
059     */
060    private final MavenProject project;
061
062    /**
063     * Default constructor using <code>Locale.ENGLISH</code> as locale.
064     * Used only in test cases.
065     */
066    public PluginXdocGenerator()
067    {
068        this.project = null;
069        this.locale = Locale.ENGLISH;
070    }
071
072    /**
073     * Constructor using <code>Locale.ENGLISH</code> as locale.
074     *
075     * @param project not null Maven project.
076     */
077    public PluginXdocGenerator( MavenProject project )
078    {
079        this.project = project;
080        this.locale = Locale.ENGLISH;
081    }
082
083    /**
084     * @param project not null.
085     * @param locale  not null wanted locale.
086     */
087    public PluginXdocGenerator( MavenProject project, Locale locale )
088    {
089        this.project = project;
090        if ( locale == null )
091        {
092            this.locale = Locale.ENGLISH;
093        }
094        else
095        {
096            this.locale = locale;
097        }
098    }
099
100
101    /**
102     * {@inheritDoc}
103     */
104    @Override
105    public void execute( File destinationDirectory, PluginToolsRequest request )
106        throws GeneratorException
107    {
108        try
109        {
110            if ( request.getPluginDescriptor().getMojos() != null )
111            {
112                @SuppressWarnings( "unchecked" ) List<MojoDescriptor> mojos = request.getPluginDescriptor().getMojos();
113
114                for ( MojoDescriptor descriptor : mojos )
115                {
116                    processMojoDescriptor( descriptor, destinationDirectory );
117                }
118            }
119        }
120        catch ( IOException e )
121        {
122            throw new GeneratorException( e.getMessage(), e );
123        }
124
125    }
126
127    /**
128     * @param mojoDescriptor       not null
129     * @param destinationDirectory not null
130     * @throws IOException if any
131     */
132    protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, File destinationDirectory )
133        throws IOException
134    {
135        File outputFile = new File( destinationDirectory, getMojoFilename( mojoDescriptor, "xml" ) );
136        try ( Writer writer = new OutputStreamWriter( new FileOutputStream( outputFile ), UTF_8 ) )
137        {
138            XMLWriter w = new PrettyPrintXMLWriter( new PrintWriter( writer ), UTF_8.name(), null );
139            writeBody( mojoDescriptor, w );
140
141            writer.flush();
142        }
143    }
144
145    /**
146     * @param mojo not null
147     * @param ext  not null
148     * @return the output file name
149     */
150    private String getMojoFilename( MojoDescriptor mojo, String ext )
151    {
152        return mojo.getGoal() + "-mojo." + ext;
153    }
154
155    /**
156     * @param mojoDescriptor not null
157     * @param w              not null
158     */
159    private void writeBody( MojoDescriptor mojoDescriptor, XMLWriter w )
160    {
161        w.startElement( "document" );
162        w.addAttribute( "xmlns", "http://maven.apache.org/XDOC/2.0" );
163        w.addAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
164        w.addAttribute( "xsi:schemaLocation",
165                        "http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd" );
166
167        // ----------------------------------------------------------------------
168        //
169        // ----------------------------------------------------------------------
170
171        w.startElement( "properties" );
172
173        w.startElement( "title" );
174        w.writeText( mojoDescriptor.getFullGoalName() );
175        w.endElement(); // title
176
177        w.endElement(); // properties
178
179        // ----------------------------------------------------------------------
180        //
181        // ----------------------------------------------------------------------
182
183        w.startElement( "body" );
184
185        w.startElement( "section" );
186
187        w.addAttribute( "name", mojoDescriptor.getFullGoalName() );
188
189        writeReportNotice( mojoDescriptor, w );
190
191        w.startElement( "p" );
192        w.writeMarkup( getString( "pluginxdoc.mojodescriptor.fullname" ) );
193        w.endElement(); //p
194        w.startElement( "p" );
195        w.writeMarkup( mojoDescriptor.getPluginDescriptor().getGroupId() + ":"
196                           + mojoDescriptor.getPluginDescriptor().getArtifactId() + ":"
197                           + mojoDescriptor.getPluginDescriptor().getVersion() + ":" + mojoDescriptor.getGoal() );
198        w.endElement(); //p
199
200        if ( StringUtils.isNotEmpty( mojoDescriptor.getDeprecated() ) )
201        {
202            w.startElement( "p" );
203            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.deprecated" ) );
204            w.endElement(); // p
205            w.startElement( "div" );
206            w.writeMarkup( GeneratorUtils.makeHtmlValid( mojoDescriptor.getDeprecated() ) );
207            w.endElement(); // div
208        }
209
210        w.startElement( "p" );
211        w.writeMarkup( getString( "pluginxdoc.description" ) );
212        w.endElement(); //p
213        w.startElement( "div" );
214        if ( StringUtils.isNotEmpty( mojoDescriptor.getDescription() ) )
215        {
216            w.writeMarkup( GeneratorUtils.makeHtmlValid( mojoDescriptor.getDescription() ) );
217        }
218        else
219        {
220            w.writeText( getString( "pluginxdoc.nodescription" ) );
221        }
222        w.endElement(); // div
223
224        writeGoalAttributes( mojoDescriptor, w );
225
226        writeGoalParameterTable( mojoDescriptor, w );
227
228        w.endElement(); // section
229
230        w.endElement(); // body
231
232        w.endElement(); // document
233    }
234
235    /**
236     * @param mojoDescriptor not null
237     * @param w              not null
238     */
239    private void writeReportNotice( MojoDescriptor mojoDescriptor, XMLWriter w )
240    {
241        if ( GeneratorUtils.isMavenReport( mojoDescriptor.getImplementation(), project ) )
242        {
243            w.startElement( "p" );
244            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.notice.note" ) );
245            w.writeText( getString( "pluginxdoc.mojodescriptor.notice.isMavenReport" ) );
246            w.endElement(); //p
247        }
248    }
249
250    /**
251     * @param mojoDescriptor not null
252     * @param w              not null
253     */
254    private void writeGoalAttributes( MojoDescriptor mojoDescriptor, XMLWriter w )
255    {
256        w.startElement( "p" );
257        w.writeMarkup( getString( "pluginxdoc.mojodescriptor.attributes" ) );
258        w.endElement(); //p
259
260        boolean addedUl = false;
261        String value;
262        if ( mojoDescriptor.isProjectRequired() )
263        {
264            addedUl = addUl( w, addedUl );
265            w.startElement( "li" );
266            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.projectRequired" ) );
267            w.endElement(); //li
268        }
269
270        if ( mojoDescriptor.isRequiresReports() )
271        {
272            addedUl = addUl( w, addedUl );
273            w.startElement( "li" );
274            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.reportingMojo" ) );
275            w.endElement(); // li
276        }
277
278        if ( mojoDescriptor.isAggregator() )
279        {
280            addedUl = addUl( w, addedUl );
281            w.startElement( "li" );
282            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.aggregator" ) );
283            w.endElement(); //li
284        }
285
286        if ( mojoDescriptor.isDirectInvocationOnly() )
287        {
288            addedUl = addUl( w, addedUl );
289            w.startElement( "li" );
290            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.directInvocationOnly" ) );
291            w.endElement(); //li
292        }
293
294        value = mojoDescriptor.isDependencyResolutionRequired();
295        if ( StringUtils.isNotEmpty( value ) )
296        {
297            addedUl = addUl( w, addedUl );
298            w.startElement( "li" );
299            w.writeMarkup( format( "pluginxdoc.mojodescriptor.dependencyResolutionRequired", value ) );
300            w.endElement(); //li
301        }
302
303        if ( mojoDescriptor instanceof ExtendedMojoDescriptor )
304        {
305            ExtendedMojoDescriptor extendedMojoDescriptor = (ExtendedMojoDescriptor) mojoDescriptor;
306
307            value = extendedMojoDescriptor.getDependencyCollectionRequired();
308            if ( StringUtils.isNotEmpty( value ) )
309            {
310                addedUl = addUl( w, addedUl );
311                w.startElement( "li" );
312                w.writeMarkup( format( "pluginxdoc.mojodescriptor.dependencyCollectionRequired", value ) );
313                w.endElement(); //li
314            }
315        }
316
317        addedUl = addUl( w, addedUl );
318        w.startElement( "li" );
319        w.writeMarkup( getString( mojoDescriptor.isThreadSafe()
320                ? "pluginxdoc.mojodescriptor.threadSafe"
321                : "pluginxdoc.mojodescriptor.notThreadSafe" ) );
322        w.endElement(); //li
323
324        value = mojoDescriptor.getSince();
325        if ( StringUtils.isNotEmpty( value ) )
326        {
327            addedUl = addUl( w, addedUl );
328            w.startElement( "li" );
329            w.writeMarkup( format( "pluginxdoc.mojodescriptor.since", value ) );
330            w.endElement(); //li
331        }
332
333        value = mojoDescriptor.getPhase();
334        if ( StringUtils.isNotEmpty( value ) )
335        {
336            addedUl = addUl( w, addedUl );
337            w.startElement( "li" );
338            w.writeMarkup( format( "pluginxdoc.mojodescriptor.phase", value ) );
339            w.endElement(); //li
340        }
341
342        value = mojoDescriptor.getExecutePhase();
343        if ( StringUtils.isNotEmpty( value ) )
344        {
345            addedUl = addUl( w, addedUl );
346            w.startElement( "li" );
347            w.writeMarkup( format( "pluginxdoc.mojodescriptor.executePhase", value ) );
348            w.endElement(); //li
349        }
350
351        value = mojoDescriptor.getExecuteGoal();
352        if ( StringUtils.isNotEmpty( value ) )
353        {
354            addedUl = addUl( w, addedUl );
355            w.startElement( "li" );
356            w.writeMarkup( format( "pluginxdoc.mojodescriptor.executeGoal", value ) );
357            w.endElement(); //li
358        }
359
360        value = mojoDescriptor.getExecuteLifecycle();
361        if ( StringUtils.isNotEmpty( value ) )
362        {
363            addedUl = addUl( w, addedUl );
364            w.startElement( "li" );
365            w.writeMarkup( format( "pluginxdoc.mojodescriptor.executeLifecycle", value ) );
366            w.endElement(); //li
367        }
368
369        if ( mojoDescriptor.isOnlineRequired() )
370        {
371            addedUl = addUl( w, addedUl );
372            w.startElement( "li" );
373            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.onlineRequired" ) );
374            w.endElement(); //li
375        }
376
377        if ( !mojoDescriptor.isInheritedByDefault() )
378        {
379            addedUl = addUl( w, addedUl );
380            w.startElement( "li" );
381            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.inheritedByDefault" ) );
382            w.endElement(); //li
383        }
384
385        if ( addedUl )
386        {
387            w.endElement(); //ul
388        }
389    }
390
391    /**
392     * @param mojoDescriptor not null
393     * @param w              not null
394     */
395    private void writeGoalParameterTable( MojoDescriptor mojoDescriptor, XMLWriter w )
396    {
397        List<Parameter> parameterList = mojoDescriptor.getParameters();
398
399        // remove components and read-only parameters
400        List<Parameter> list = filterParameters( parameterList );
401
402        if ( !list.isEmpty() )
403        {
404            writeParameterSummary( mojoDescriptor, list, w );
405
406            writeParameterDetails( mojoDescriptor, list, w );
407        }
408        else
409        {
410            w.startElement( "subsection" );
411            w.addAttribute( "name", getString( "pluginxdoc.mojodescriptor.parameters" ) );
412
413            w.startElement( "p" );
414            w.writeMarkup( getString( "pluginxdoc.mojodescriptor.noParameter" ) );
415            w.endElement(); //p
416
417            w.endElement();
418        }
419    }
420
421    /**
422     * Filter parameters to only retain those which must be documented, ie not components nor readonly.
423     *
424     * @param parameterList not null
425     * @return the parameters list without components.
426     */
427    private List<Parameter> filterParameters( List<Parameter> parameterList )
428    {
429        List<Parameter> filtered = new ArrayList<>();
430
431        if ( parameterList != null )
432        {
433            for ( Parameter parameter : parameterList )
434            {
435                if ( parameter.isEditable() )
436                {
437                    String expression = parameter.getExpression();
438
439                    if ( expression == null || !expression.startsWith( "${component." ) )
440                    {
441                        filtered.add( parameter );
442                    }
443                }
444            }
445        }
446
447        return filtered;
448    }
449
450    /**
451     * @param mojoDescriptor not null
452     * @param parameterList  not null
453     * @param w              not null
454     */
455    private void writeParameterDetails( MojoDescriptor mojoDescriptor, List<Parameter> parameterList, XMLWriter w )
456    {
457        w.startElement( "subsection" );
458        w.addAttribute( "name", getString( "pluginxdoc.mojodescriptor.parameter.details" ) );
459
460        for ( Iterator<Parameter> parameters = parameterList.iterator(); parameters.hasNext(); )
461        {
462            Parameter parameter = parameters.next();
463
464            w.startElement( "h4" );
465            w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.name_internal", parameter.getName() ) );
466            w.endElement();
467
468            if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) )
469            {
470                w.startElement( "div" );
471                w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.deprecated",
472                                       GeneratorUtils.makeHtmlValid( parameter.getDeprecated() ) ) );
473                w.endElement(); // div
474            }
475
476            w.startElement( "div" );
477            if ( StringUtils.isNotEmpty( parameter.getDescription() ) )
478            {
479                w.writeMarkup( GeneratorUtils.makeHtmlValid( parameter.getDescription() ) );
480            }
481            else
482            {
483                w.writeMarkup( getString( "pluginxdoc.nodescription" ) );
484            }
485            w.endElement(); // div
486
487            boolean addedUl = false;
488            addedUl = addUl( w, addedUl, parameter.getType() );
489            writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.type" ), parameter.getType(), w );
490
491            if ( StringUtils.isNotEmpty( parameter.getSince() ) )
492            {
493                addedUl = addUl( w, addedUl );
494                writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.since" ), parameter.getSince(), w );
495            }
496            else
497            {
498                if ( StringUtils.isNotEmpty( mojoDescriptor.getSince() ) )
499                {
500                    addedUl = addUl( w, addedUl );
501                    writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.since" ), mojoDescriptor.getSince(),
502                                 w );
503                }
504            }
505
506            if ( parameter.isRequired() )
507            {
508                addedUl = addUl( w, addedUl );
509                writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), getString( "pluginxdoc.yes" ),
510                             w );
511            }
512            else
513            {
514                addedUl = addUl( w, addedUl );
515                writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.required" ), getString( "pluginxdoc.no" ),
516                             w );
517            }
518
519            String expression = parameter.getExpression();
520            addedUl = addUl( w, addedUl, expression );
521            String property = getPropertyFromExpression( expression );
522            if ( property == null )
523            {
524                writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.expression" ), expression, w );
525            }
526            else
527            {
528                writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.property" ), property, w );
529            }
530
531            addedUl = addUl( w, addedUl, parameter.getDefaultValue() );
532            writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.default" ),
533                         escapeXml( parameter.getDefaultValue() ), w );
534
535            addedUl = addUl( w, addedUl, parameter.getAlias() );
536            writeDetail( getString( "pluginxdoc.mojodescriptor.parameter.alias" ), escapeXml( parameter.getAlias() ),
537                         w );
538
539            if ( addedUl )
540            {
541                w.endElement(); //ul
542            }
543
544            if ( parameters.hasNext() )
545            {
546                w.writeMarkup( "<hr/>" );
547            }
548        }
549
550        w.endElement();
551    }
552
553    private boolean addUl( XMLWriter w, boolean addedUl, String content )
554    {
555        if ( StringUtils.isNotEmpty( content ) )
556        {
557            return addUl( w, addedUl );
558        }
559        return addedUl;
560    }
561
562    private boolean addUl( XMLWriter w, boolean addedUl )
563    {
564        if ( !addedUl )
565        {
566            w.startElement( "ul" );
567            addedUl = true;
568        }
569        return addedUl;
570    }
571
572    private String getPropertyFromExpression( String expression )
573    {
574        if ( StringUtils.isNotEmpty( expression ) && expression.startsWith( "${" ) && expression.endsWith( "}" )
575            && !expression.substring( 2 ).contains( "${" ) )
576        {
577            // expression="${xxx}" -> property="xxx"
578            return expression.substring( 2, expression.length() - 1 );
579        }
580        // no property can be extracted
581        return null;
582    }
583
584    /**
585     * @param param not null
586     * @param value could be null
587     * @param w     not null
588     */
589    private void writeDetail( String param, String value, XMLWriter w )
590    {
591        if ( StringUtils.isNotEmpty( value ) )
592        {
593            w.startElement( "li" );
594            w.writeMarkup( format( "pluginxdoc.detail", new String[]{ param, value } ) );
595            w.endElement(); //li
596        }
597    }
598
599    /**
600     * @param mojoDescriptor not null
601     * @param parameterList  not null
602     * @param w              not null
603     */
604    private void writeParameterSummary( MojoDescriptor mojoDescriptor, List<Parameter> parameterList, XMLWriter w )
605    {
606        List<Parameter> requiredParams = getParametersByRequired( true, parameterList );
607        if ( requiredParams.size() > 0 )
608        {
609            writeParameterList( mojoDescriptor, getString( "pluginxdoc.mojodescriptor.requiredParameters" ),
610                                requiredParams, w );
611        }
612
613        List<Parameter> optionalParams = getParametersByRequired( false, parameterList );
614        if ( optionalParams.size() > 0 )
615        {
616            writeParameterList( mojoDescriptor, getString( "pluginxdoc.mojodescriptor.optionalParameters" ),
617                                optionalParams, w );
618        }
619    }
620
621    /**
622     * @param mojoDescriptor not null
623     * @param title          not null
624     * @param parameterList  not null
625     * @param w              not null
626     */
627    private void writeParameterList( MojoDescriptor mojoDescriptor, String title, List<Parameter> parameterList,
628                                     XMLWriter w )
629    {
630        w.startElement( "subsection" );
631        w.addAttribute( "name", title );
632
633        w.startElement( "table" );
634        w.addAttribute( "border", "0" );
635
636        w.startElement( "tr" );
637        w.startElement( "th" );
638        w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.name" ) );
639        w.endElement(); //th
640        w.startElement( "th" );
641        w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.type" ) );
642        w.endElement(); //th
643        w.startElement( "th" );
644        w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.since" ) );
645        w.endElement(); //th
646        w.startElement( "th" );
647        w.writeText( getString( "pluginxdoc.mojodescriptor.parameter.description" ) );
648        w.endElement(); //th
649        w.endElement(); //tr
650
651        for ( Parameter parameter : parameterList )
652        {
653            w.startElement( "tr" );
654
655            // name
656            w.startElement( "td" );
657            w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.name_link", parameter.getName() ) );
658            w.endElement(); //td
659
660            //type
661            w.startElement( "td" );
662            int index = parameter.getType().lastIndexOf( "." );
663            w.writeMarkup( "<code>" + parameter.getType().substring( index + 1 ) + "</code>" );
664            w.endElement(); //td
665
666            // since
667            w.startElement( "td" );
668            if ( StringUtils.isNotEmpty( parameter.getSince() ) )
669            {
670                w.writeMarkup( "<code>" + parameter.getSince() + "</code>" );
671            }
672            else
673            {
674                if ( StringUtils.isNotEmpty( mojoDescriptor.getSince() ) )
675                {
676                    w.writeMarkup( "<code>" + mojoDescriptor.getSince() + "</code>" );
677                }
678                else
679                {
680                    w.writeMarkup( "<code>-</code>" );
681                }
682            }
683            w.endElement(); //td
684
685            // description
686            w.startElement( "td" );
687            String description;
688            if ( StringUtils.isNotEmpty( parameter.getDeprecated() ) )
689            {
690                description = format( "pluginxdoc.mojodescriptor.parameter.deprecated",
691                                      GeneratorUtils.makeHtmlValid( parameter.getDeprecated() ) );
692            }
693            else if ( StringUtils.isNotEmpty( parameter.getDescription() ) )
694            {
695                description = GeneratorUtils.makeHtmlValid( parameter.getDescription() );
696            }
697            else
698            {
699                description = getString( "pluginxdoc.nodescription" );
700            }
701            w.writeMarkup( description + "<br/>" );
702
703            if ( StringUtils.isNotEmpty( parameter.getDefaultValue() ) )
704            {
705                w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.defaultValue",
706                                       escapeXml( parameter.getDefaultValue() ) ) );
707                w.writeMarkup( "<br/>" );
708            }
709
710            String property = getPropertyFromExpression( parameter.getExpression() );
711            if ( property != null )
712            {
713                w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.property.description", property ) );
714                w.writeMarkup( "<br/>" );
715            }
716
717            if ( StringUtils.isNotEmpty( parameter.getAlias() ) )
718            {
719                w.writeMarkup( format( "pluginxdoc.mojodescriptor.parameter.alias.description",
720                                       escapeXml( parameter.getAlias() ) ) );
721            }
722
723            w.endElement(); //td
724            w.endElement(); //tr
725        }
726
727        w.endElement(); //table
728        w.endElement(); //section
729    }
730
731    /**
732     * @param required      <code>true</code> for required parameters, <code>false</code> otherwise.
733     * @param parameterList not null
734     * @return list of parameters depending the value of <code>required</code>
735     */
736    private List<Parameter> getParametersByRequired( boolean required, List<Parameter> parameterList )
737    {
738        List<Parameter> list = new ArrayList<>();
739
740        for ( Parameter parameter : parameterList )
741        {
742            if ( parameter.isRequired() == required )
743            {
744                list.add( parameter );
745            }
746        }
747
748        return list;
749    }
750
751    /**
752     * Gets the resource bundle for the <code>locale</code> instance variable.
753     *
754     * @return The resource bundle for the <code>locale</code> instance variable.
755     */
756    private ResourceBundle getBundle()
757    {
758        return ResourceBundle.getBundle( "pluginxdoc", locale, getClass().getClassLoader() );
759    }
760
761    /**
762     * @param key not null
763     * @return Localized, text identified by <code>key</code>.
764     * @see #getBundle()
765     */
766    private String getString( String key )
767    {
768        return getBundle().getString( key );
769    }
770
771    /**
772     * Convenience method.
773     *
774     * @param key  not null
775     * @param arg1 not null
776     * @return Localized, formatted text identified by <code>key</code>.
777     * @see #format(String, Object[])
778     */
779    private String format( String key, Object arg1 )
780    {
781        return format( key, new Object[]{ arg1 } );
782    }
783
784    /**
785     * Looks up the value for <code>key</code> in the <code>ResourceBundle</code>,
786     * then formats that value for the specified <code>Locale</code> using <code>args</code>.
787     *
788     * @param key  not null
789     * @param args not null
790     * @return Localized, formatted text identified by <code>key</code>.
791     */
792    private String format( String key, Object[] args )
793    {
794        String pattern = getString( key );
795        // we don't need quoting so spare us the confusion in the resource bundle to double them up in some keys
796        pattern = StringUtils.replace( pattern, "'", "''" );
797
798        MessageFormat messageFormat = new MessageFormat( "" );
799        messageFormat.setLocale( locale );
800        messageFormat.applyPattern( pattern );
801
802        return messageFormat.format( args );
803    }
804
805    /**
806     * @param text the string to escape
807     * @return A string escaped with XML entities
808     */
809    private String escapeXml( String text )
810    {
811        if ( text != null )
812        {
813            text = text.replaceAll( "&", "&amp;" );
814            text = text.replaceAll( "<", "&lt;" );
815            text = text.replaceAll( ">", "&gt;" );
816            text = text.replaceAll( "\"", "&quot;" );
817            text = text.replaceAll( "\'", "&apos;" );
818        }
819        return text;
820    }
821
822}