New page: This is a copy of netbeans:APIDevelopment page created for archiving purposes. ==API Development== '''Changes:''' available in [http://www.netbeans.org/source/browse/openide/www/tuto...
New page
This is a copy of [[netbeans:APIDevelopment]] page created for archiving purposes.
==API Development==
'''Changes:''' available in [http://www.netbeans.org/source/browse/openide/www/tutorial/api.html CVS]
'''Status:'' {{iz|26785}}
===Overview===
The [[NetBeans]] project provides a rich set of [http://bits.netbeans.org/dev/javadoc/ APIs] that is being developed as part of work of various groups. By distributing development of the [[API]]s to multiple people we can increase the amount of designed, reviewed, implemented, tuned and maintained contracts but as each module is developed by a different person, there is a challenge in providing [[API]]s of the same quality, designed by using the same patterns and documented in a common way. This document describes the practices that should be used during the [[API]] development, so [[NetBeans]] can produce [[API]]s that will stand the test of time and preserve investments made by its customers.
__TOC__
===Describing APIs===
We understand the APIs as every aspect another piece of system can depend on and not just method signature. That is why providing documentation in form of javadoc is not usually be enough. Instead NetBeans projects use document generated from answers to Architecture Questions as main entry point. The questions provide guidance to the module owner and help him investigate architecture of his own module. By answering them the owner is supposed to realize and discover various aspects that others might depend on and remove them or document them. Based on the detailed answers (especially the <tt><api/></tt> tag) we generate overview tables like the one shown below that are incorporated into the Javadoc.
{|
! Interface Name
! Stability Classification
! Specified in What Document?
|-
| ProviderRegistrationRemoval
| [http://openide.netbeans.org/tutorial/api-design.html#category-devel Under Development]
| [http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/doc-files/api.html#service-lookup api.html]
|-
|LookupAPI
|[http://openide.netbeans.org/tutorial/api-design.html#category-official Official]
|[http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/doc-files/api.html#lookup #lookup]
|-
|LookupSPI
|[http://openide.netbeans.org/tutorial/api-design.html#category-official Official]
|[http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/package-frame.html package-frame.html]
|-
|Set of property APIs
|Individual
|[http://www.netbeans.org/download/dev/javadoc/org-openide-util/architecture-summary.html#group-property table with definitions]
|}
====Setting up the infrastructure====
If you write a NetBeans module you may want to setup the right layout of files first. The default infrastructure ([http://www.netbeans.org/source/browse/~checkout~/nbbuild/templates/common.xml nbbuild/templates/common.xml] and [http://www.netbeans.org/source/browse/~checkout~/nbbuild/templates/projectized.xml nbbuild/templates/projectized.xml]) let you do various tweaks, but usually it is easier to just use the expected default layout (currently described in [http://www.netbeans.org/source/browse/~checkout~/apisupport/harness/README README]). The documentation related files shall be organized as follows:
<pre>
module_dir/src/ - directory with your sources
module_dir/src/**/package.html - description of each package
module_dir/src/**/doc-files/ - directory for special javadoc files
module_dir/arch.xml - answers to architecture questions (see bellow)
module_dir/apichanges.xml - description of the history of changes
module_dir/nbproject/project.xml - project file with dependencies and other informations
</pre>
The locations of arch.xml and apichanges.xml moreover has to be specified in [http://www.netbeans.org/source/browse/~checkout~/projects/projectapi/nbproject/project.properties nbproject/project.properties] as <tt>javadoc.arch=${basedir}/arch.xml</tt> and <tt>javadoc.apichanges=${basedir}/apichanges.xml</tt>.
====Writing the documentation====
# '''Generate arch.xml''' - open your project in NetBeans and select <em>Generate Architecture Description</em> from a context menu in projects tab. An empty, skeleton file will be generated. You can always reinvoke this target, if your answers are old, unanswered questions will be generated to the end of the file (the file shall stay well formated). When editing the file you can use <b>HTML tags</b>. <br><br>Some of the answers may have autogenerated default answers (currently arch-where and dep-nb) for cases where the information is already recorded anywhere else (for example in project.xml file). They may or may not be accurate. You can <b>accept</b> the generated answer while surrounding it with your additional comments or you can <b>suppress</b> it. Just include <code><defaultanswer generate='here' /></code> or <code><defaultanswer generate='none' /></code> in the answer of for your question. If you do not use the <code><defaultanswer/></code> element at all the default answer is <b>apended</b> to your own answer. If you generate the defaultanswer, the source code for it is put into the comments in the html file, so if you are not satisified with the defaults, you can easily copy the output modify it and <code><defaultanswer generate='none' /></code>.
# '''Use <api/> tag''' - this tag is one of the most important in the architecture file. Each use of the <api> tags generates new item into a table of API interfaces. This is the main entry point to the documentation, so use the tag a lot. Not just for a description of javadoc interfaces, but for everything. Remember that an api is [APIDesign|any feature that someone else rely on]. Describe DTDs, properties, files or layers you read, formats or protocols that you communicate, etc. The <tt><api/></tt> tag syntax is described by its DTD and consists of:
#: '''name''' - the name of the API, DTD or property
#: '''group''' - the group that this API belongs. For example "property", "java", "dtd", "layer" and possibly others. As we are writing in java the attribute can be omitted and the default value is "java".
#: '''type''' - you can either use someone else API ("import") or offer someone else dependency on your behavior ("export").
#: '''category''' - shall contain a name from the enumeration (<tt>official</tt>, <tt>stable</tt>, <tt>devel</tt>, <tt>third</tt>, <tt>standard</tt>, <tt>friend</tt>, <tt>private</tt>, <tt>deprecated</tt>) in the meaning described [[APIDesign#categories|here]].
#: '''url''' - shall refer to a document describing the API, if available otherwise one can insert additional comments into the body between the <tt><api></tt> and <tt></api></tt>.
#: An example is available here:<br/><tt><api name="identification" group="dtd" type="import or export" category="stable" url="where is the description" >Possibly some additional description to the API which may be skipped. </api></tt><br/>The interfaces in the table are grouped by the group of the API and marked in the HTML text as <tt><a name="group-name" /></tt> so a reference to these tables can be made by using <tt><a href="#group-name" /></tt>.
# '''Use <usecase> tag''' - when answering "arch-usecases" question, surround the paragraphs describing the way to use your API with <tt><usecase name="..." id="..."></tt> and <tt></usecase></tt>. That way your paragraph will get correct heading in the [http://www.netbeans.org/download/dev/javadoc/usecases.html How to use certain NetBeans APIs] page.
# '''Answer "arch-what"'''' - the first sentence of your answer to "arch-what" is used as a short description in the [http://www.netbeans.org/download/dev/javadoc/overview-summary.html overview page] so write it meaningfully. The full answer is then used in [http://www.netbeans.org/download/dev/javadoc/overview-summary.html#def-api-Terminal%20Emulator the details] section, so again, make it real and useful description of your module.
# '''Link between documents''' - important part of documentation is the description of context. It is not enough to say: "find this interfacein lookup". The reader may not know what "lookup" is, so it is better to hyperlink to its definition. You can use regular <tt><a href></tt> tag to link to other documents, for root of your javadoc use '''@TOP@'''. So link to lookup would be <tt>@TOP@/org/openide/util/Lookup.html</tt>.
# '''Link between classes''' - consider making the prose section part of <tt>package.html</tt> file. Then you can use '''@{link classname}''' to address any class of your module or from modules you depend on.
# '''Link between Javadoc sets''' - the context is often split between multiple modules. To allow links between them, the root of each module javadoc can be referred to as '''@org-netbeans-the-module-code-base-name@'''. So to link to lookup from another module one can use <tt>@org-openide-util@/org/openide/util/Lookup.html</tt> (the list of all currently known module name substitutions is available at [http://www.netbeans.org/source/browse/~checkout~/nbbuild/javadoctools/replaces.xml?content-type=text/plain nbbuild/javadoctools/replaces.xml]).
# '''Use Relative Links''' - please remove as much as possible of usages of non-relative links like http://www.netbeans.org/download/dev/javadoc and replace them with '''@TOP@''', '''@org-netbeans-module-name@''' or '''@JDK@''' root points. The javadoc is being scanned for allowed and disallowed links (defined in [http://www.netbeans.org/source/browse/nbbuild/javadoctools/disallowed-links.xml nbbuild/javadoctools/disallowed-links.xml]) and violations cause the build run from IDE to fail. It is generally not recommended to refer to NetBeans website as the documentation shall be self contained, but if you find a URL that makes sence, feel free to add it to the [http://www.netbeans.org/source/browse/nbbuild/javadoctools/disallowed-links.xml nbbuild/javadoctools/disallowed-links.xml] yourself. Btw. it seems better to use such pseudo root point than directly relative link as for example content of package.html is usually duplicated into more directories.
# '''Create apichanges''' - important part of any api is history of its changes. That is why create and maintain the [http://www.netbeans.org/source/browse/~checkout~/openide/loaders/api/apichanges.xml apichanges.xml] as described in NetBeans [[VersioningPolicy]]. When you refer to a class that no longer exists inside an API change, you can use <tt><class ... link="no"/></tt>.
# '''Validate your documentation''' - make sure the documentation format is correct (links point to valid places, XML files has valid syntax, etc.). This can be checked by invoking "Generate Javadoc" from the context menu. This builds the Javadoc and (in addition to invoking <code>ant javadoc</code> from command line) also checks for broken links and fails if there any - so make sure all Javadoc of modules you are referring to has already been generated.
====Publishing Javadoc====
All NetBeans project Javadoc sets are being daily regenerated and uploaded to the central [http://www.netbeans.org/download/dev/javadoc/ NetBeans API List]. When your module can successfully build javadoc as described in previous section, it is time to consider adding it to the API list as well. <br/><br/>To add it, you have to modify [http://www.netbeans.org/source/browse/nbbuild/build.properties.diff?r1=1.261&r2=1.262 nbbuild/build.properties] and add own module into <tt>config.fixedmodules.javadoc</tt> property. Use<pre>
ant -f nbbuild/build.xml check-module-configs
cvs -q diff nbbuild
</pre>
to review your changes. Then verify that everything works correctly by rebuilding all Javadoc:
<tt>ant -f nbbuild/build.xml build-javadoc</tt> <br/><br/>and if the build succeeds and really contains your module, prepare for committing your changes into CVS (check in the new <tt>moduleconfigs.txt</tt> too). Please note that three files in <tt>nbbuild/javadoctools</tt>
shall be modified by addition of references to your module root. Verify that the additions are sane (e.g. contain no local references and look like the other lines in the files) and then commit the modified
[http://www.netbeans.org/source/browse/nbbuild/build.properties.diff?r1=1.261&r2=1.262 nbbuild/build.properties], [http://www.netbeans.org/source/browse/nbbuild/javadoctools/replaces.xml.diff?r1=1.3&r2=1.4 nbbuild/javadoctools/replaces.xml],
[http://www.netbeans.org/source/browse/nbbuild/javadoctools/links.xml.diff?r1=1.2&r2=1.3 nbbuild/javadoctools/links.xml] and
[http://www.netbeans.org/source/browse/nbbuild/javadoctools/properties.xml.diff?r1=1.2&r2=1.3 nbbuild/javadoctools/properties.xml].
====Javadoc Tips====
By default the basic overview page is generated based on content of your [http://www.netbeans.org/source/browse/~checkout~/apisupport/project/arch.xml arch.xml],
[http://www.netbeans.org/source/browse/~checkout~/java/project/apichanges.xml apichanges.xml]
and [http://www.netbeans.org/source/browse/~checkout~/java/project/nbproject/project.xml project.xml].
To see an example, check the [http://www.netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/overview-summary.html overview page of component palette api].
This page has following structure:
# '''Title and description''' is taken from the <tt>arch.xml</tt>'s answer to question <tt>arch-overall</tt>.
# '''List of javadoc packages''' is added by the default javadoc doclet.
# '''what is new section''' lists five recent api changes listed in <tt>apichanges.xml</tt>. Always add at least one change as this document is used to generate what is [http://www.netbeans.org/download/dev/javadoc/apichanges.html new for the whole release].
# '''List of usecases''' is taken from the <tt>arch.xml</tt> answer to <tt>arch-usecases</tt> question. It shall contain the main introduction into the meaning and usage of the API. Links to javadoc classes and methods are welcomed. Also notice that the answer contributed to [http://www.netbeans.org/download/dev/javadoc/usecases.html global page with usecases] for all NetBeans APIs.
# '''Implementation details''' close the summary page. The contain answer to <tt>arch-where</tt> question, which shall contain link to NetBeans WebCVS with the module sources like http://www.netbeans.org/source/browse/~checkout~/java/project/ for the [http://www.netbeans.org/source/browse/~checkout~/java/project/ java/project] module. Also an answer to <tt>deploy-dependencies</tt> arch question is generated so other modules know how to express dependency on this one.
'''XXX''' need to describe: <tt>{@link ...}</tt>, what <tt>package.html</tt> can and cannot do, <tt>@inheritDoc</tt>, etc.
===Reviewing APIs===
In order to ensure good enough quality of produced APIs there is a service provided to module writers - they can ask for an API review.
It is required that every new API will be reviewed prior to integration into trunk. The exception from this rule is a <tt>friend</tt> API that is used only by modules within the same cluster (the module has to explicitly list its friends). In this case the review is recommended but not required.
====Why?====
The short answer to question why you should be interested in an architecture review is "because it will be useful". Useful to you, as you discover new possible solutions to your problems or mistakes in your design, that might appear later, when integrated together with the whole system or even in later versions, when problems with maintainability and extensibility can show up. It will be useful to the whole system as it will be composed from more stable components integrated in better ways. It will be useful to whole your project as it will get better.
Nobody knows everything, but there is a lot of knowledge spread around. Architecture review is a way to get the people with pieces of knowledge together and cooperate in preventing us from repeating known mistakes and solving problems in the wrong way.
Ask for advice through architecture review. It cannot hurt and it is likely going to be useful.
====What?====
It is unlikely that the review team will do some coding for you. It is also unlikely that the reviewers are going to become domain experts and help you understand your users or your requirements. This is your task and you have to prepare these materials for the reviewers, as it is very likely they will ask you about these questions in order to verify that your way of solving problems of your users is really the right one.
As a result of architecture review you can expect advices and help in identification of
* [[APIDesign#api|apis] that someone else could depend on,
* design or implementation that might have performance problems,
* influences of your solution on existing products or
* influences of other products on your solution in future,
* solutions that are solving something different than was the original goal and
* other projects or efforts going around that might help you in solving your problems.
More or less expect "just" a high level help.
====When?====
Whenever you need architecture advice or clarification and because the charter of the team is mostly high level, it is reasonable to come for the initial opinion as soon as the architecture is visible so it can be reviewed. This usually means after answering the first (more general) set of the architecture questions which should be done before the actual start of implementation. At this point the high level advices are of some use, later it is always hard to change implementation that has been written.
Of course things are likely change during implementation, but the high level direction given during this ''inception'' stage are likely not going to be questioned then and only the newly discovered facts and differences from the original suggestions are going to be evaluated during the ''before-commit'' review.
====How?====
For details about the process see the Architecture Review Steps document or check the list of all reviews.
===Testing APIs===
====Why?====
If an API is supposed to stand the test of time it has to preserve the functionality that others are using, it has to be backward compatible. Some tests for compatibility are easy, some require more work, but the testing is necessary otherwise nobody can guarantee quality when the API is evolving.
[[#sigtests|Signature tests]] are simple starting point, [[#unittests|unit tests]] are very good for verifying the "contract" between a public API and its clients. Some people claim that unit tests are poorly named since they imply that they are QA's responsibility, but the development engineer is the one that really
benefits with several advantages:
* the tests provide an example of how the developer expects the API to be used.
* Another is that when you run code coverage against a unit test suite, it shows surprising areas where there is code that isn't necessary to support the API, so one can easily remove those extra bits
* Another interesting feature of unit tests is support of arrogance (which is part of all good programmers). So here's the best, most compelling reason for creating and relying on unit tests: you can much more confidently tell another engineer how wrong he is when he claims your code is breaking his!
Read more about possible test patterns that we use and how they can contribute to improvements in quality of your module.
====Signature Tests====
There is an automated verification task that is executed after every daily build that checks signature of classes and their fields and methods and sends reports to [http://netbeans.org/projects/www/lists/api-changes/archive api-changes] mailing list. Its reports contain both incompatible and compatible changes. So one gets notified not only when something is broken, but also in case of accidental API change like addition of a method by forgetting to make it
<tt>private</tt>.
By default the tests check all classes in [[APIDesign#category-official|official]] packages. E.g.
<tt>org.openide.*</tt>, <tt>org.netbeans.api.*</tt> and <tt>org.netbeans.spi.*</tt> and recently also <tt>org.netbeans.jmi</tt> that are part of modules included in daily build of standard IDE and also those that are daily uploaded to <em>Alpha Update Center</em>. That is why in order to have these tests running on own module one has to package the API into one of the official package (or
[mailto:nbdev@netbeans.org request] his own package to be added into the test) and make the module part alpha autoupdate configuration.
Any questions related to the sigtest framework can be either sent to [mailto:nbdev@netbeans.org nbdev@] or to [mailto:rbalada@netbeans.org Rudolf Balada] who maintains the daily build (including sigtest) infrastructure.
====Unit Tests====
Very important verification of quality of an API is an automated test suite. Most of NetBeans modules uses our test harness called [http://xtest.netbeans.org xtest] which is based on [http://www.junit.org JUnit] and enhances it with a few additional features (tests should inherit from [http://www.netbeans.org/source/browse/~checkout~/xtest/nbjunit/src/org/netbeans/junit/NbTestCase.java NbTestCase]) and configuration framework.
The simplest way how to make your module testable is to copy the <tt>test</tt> directory from a small modules that already provide some tests and modify it (e.g. [http://www.netbeans.org/source/browse/html/test/ html]). The needed changes include classpath modifications for compilation and execution in <tt>build.xml</tt>, correcting the list of tests in
<tt>cfg-unit.xml</tt> and of course the placing your own tests into <tt>unit/src</tt> directory.
The last step is to include the suite in daily execution of unit tests. For that it is enough to modify the
[http://www.netbeans.org/source/browse/~checkout~/xtest/instance/master-config.xml xtest/instance/master-config.xml] to include your module in the '''unit-nb''' test config. Verify that you have done everything correctly by running<pre>ant -f nbbuild/build.xml unit-validation</pre>
and checking that your tests were successfully executed. Since then make sure that your module tests really run and pass, as since then other people start to use these tests to verify validity of their own commits. And you should not cause false alarms by problems in your code.
Also consider to subscribe to [http://beetle.czech:8080/unittest/ notification framework] to get email notifications about automatic failures, if you can reach the URL.
===Deploying the APIs===
The important part in a [[APIDesign#life|life cycle]] of an API (as well as any other product) is the feedback from the users. In order to get it one should let your users know that there is an API and allow they to try it. For that purpose NetBeans use its "Alpha Update Center". Curious users may enable it and
that way be informed about latest development achievements.
To get a module into the "Alpha Update Center" one needs to make sure that the module's <tt>build.xml</tt> file has <tt>netbeans</tt>, <tt>clean</tt>, and <tt>nbm</tt> targets that work in the normal way - normally this is accomplished trivially by making a projectized module and not overriding any targets from the default build harness.Then one can add entries for the new module to <tt>nbbuild/build.properties</tt> in the list <tt>config.modules.daily-alpha-nbms</tt>. Use<pre>
ant -f nbbuild/build.xml check-module-configs
cvs diff ide/golden/moduleconfigs.txt
</pre>to review your changes (check in the new <tt>moduleconfigs.txt</tt> too).
<br/>
One should test the NBM building process on local disk by making sure you have everything of interest checked out from CVS, opening <tt>nbbuild</tt> as a project in the IDE, and selecting '''Build Daily Alpha NBMs''' from its context menu. If something is messed up, mail gets sent to <tt>broken_builds@netbeans.org</tt> so it can be corrected. It is a good idea to notify
[mailto:aumasters@netbeans.org?subject=FYI:%20adding/updating%20daily%20alpha%20NBMs <tt>aumasters@netbeans.org</tt>] too.
====Publishing New Versions====
The content of "Alpha Update Center" is refreshed every day. The new version of module NBM is build from trunk and specification version in its module manifest is compared to the specification version of already uploaded module. If the new one is greater, the new version of the module replaces the old one.
This means that one can consciously and automatically upload new versions of an API from trunk to its users just by increasing the specification version in the CVS manifest file.
===Stabilize the APIs===
Usually an attempt to produce an API requires longer development time and it is useful to mark it as not being finished yet. NetBeans use a set of [[APIDesign#life|stability categories] for that.
The expected scenario is that a module with an API starts its development in a CVS sandbox ([http://www.netbeans.org/community/contribute/modules.html contrib.netbeans.org]) or as a regular '''netbeans.org''' project (like [http://xml.netbeans.org xml.netbeans.org]) but is not part of the regular build. Then it is offered on Alpha or Beta AutoUpdate (early access mode) and one can work on its finalization. As the module is not part of a stable release, it can be modified in incompatible way. As soon as one thinks that the API is fine and it satisfies [http://qa.netbeans.org/processes/stabe_module_criteria_process.html quality criteria], it can be put on "Stable Update Center" or even find its way into standard distribution.
====Official APIs Restrictions====
There is however one restriction. In order to make it easy for API users to find out what is stable API we have come with a simple description: "If a class is in <tt>org.netbeans.api.*</tt> or <tt>org.netbeans.spi.*</tt> packages, and is part of a stable release, then it is [[APIDesign#category-stable|stable]]". Such API is then called NetBeans [[APIDesign#category-official|Official]] API.
This rule is not meant to block anyone in producing APIs. One can always create an API in less prominent package (say [http://www.netbeans.org/download/dev/javadoc/#def-api-ant org.netbeans.modules.ant.api]), publish it on netbeans.org as [[APIDesign#category-stable|stable]] one and use all the infrastructure for API development that is available. Moreover this approach is not as strict and allows the API to be part of a release even if it has not reached enough stability for unlimited amount of time.
====Support for Early Adoption====
There can be situations when strictly following the "official namespace restriction" may cause a lot of troubles to early adopters and hurt NetBeans acceptance and competitiveness. Sometimes one needs to provide an API quickly, cannot guarantee that it is that [[APIDesign#category-stable|stable]], but is strongly willing to stabilize it in <em>close future</em>. In such case it may be acceptable to release the API in official packages, mark it as [[APIDesign#category-devel|under development]] (by warning in javadoc and special name of the module) and stabilize it in next release. In such cases it may be possible to allow a temporary release of an API [[APIDesign|under development]] in official namespace if following is guaranteed:
* the API is intended to become [[APIDesign#category-stable|stable]]
* making it [[APIDesign#category-stable|stable] has been agreed to be the highest priority for next release
* the API is of "nearly stable" quality - documented, tested, published and successfully reviewed
The purpose of this "temporary release" is to encourage early adopters to test the APIs in real world and provide feedback to make them better. The publishers of the APIs in return promise to stabilize them soon and do that carefully considering the user impact. As a result NetBeans should be able to deliver important APIs as soon as possible, offer them to early adopters and increase API quality by incorporating the feedback. The adopters could be sure that the APIs will be stabilized in a given time frame and that they will not need to do major changes (like repackaging of all import statements, which was the current strategy) when the API becomes stable. In order to clearly communicate the exceptional state of the APIs, there should be a visible and non-ignorable stamp that such APIs are [[APIDesign#category-devel|under development]]:
* the javadoc documentation headers shall contain visible warnings
* the module name shall indicate that it is not stable yet. This shall be done using "/0" in module name, for example <tt>org.netbeans.api.projects.ant/0</tt>. As this string has to be used by every module writer to specify module dependency it forms appropriate warning. When stable version of the module is produced and is incompatible with the "/0" version, the name should change to <tt>org.netbeans.api.projects.ant/2</tt>. If the stable version remains compatible the name of the module should be <tt>org.netbeans.api.projects.ant/1</tt> and appropriate [http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#refactoring ModuleAutoDeps] shall be provided to upgrade dependencies of modules that used the "/0" version.
These suggestions shall ensure that the right balance is achieved between produces and consumers of any NetBeans API. It should however be stated that nobody shall be restricted by "Official namespace restriction" or bound by a time limit of the "temporary release", because if one does not want to create stable API, one does not have to. Contributing to [[APIDesign#category-official|official]] API set shall be a privilege as such effort requires more attention and increased amount of work that only those who really care are willing to invest.
{{information|Comments or corrections to [mailto:nbdev@netbeans.org nbdev@netbeans.org] or [mailto:apireviews@netbeans.org apireviews@netbeans.org].}}
==API Development==
'''Changes:''' available in [http://www.netbeans.org/source/browse/openide/www/tutorial/api.html CVS]
'''Status:'' {{iz|26785}}
===Overview===
The [[NetBeans]] project provides a rich set of [http://bits.netbeans.org/dev/javadoc/ APIs] that is being developed as part of work of various groups. By distributing development of the [[API]]s to multiple people we can increase the amount of designed, reviewed, implemented, tuned and maintained contracts but as each module is developed by a different person, there is a challenge in providing [[API]]s of the same quality, designed by using the same patterns and documented in a common way. This document describes the practices that should be used during the [[API]] development, so [[NetBeans]] can produce [[API]]s that will stand the test of time and preserve investments made by its customers.
__TOC__
===Describing APIs===
We understand the APIs as every aspect another piece of system can depend on and not just method signature. That is why providing documentation in form of javadoc is not usually be enough. Instead NetBeans projects use document generated from answers to Architecture Questions as main entry point. The questions provide guidance to the module owner and help him investigate architecture of his own module. By answering them the owner is supposed to realize and discover various aspects that others might depend on and remove them or document them. Based on the detailed answers (especially the <tt><api/></tt> tag) we generate overview tables like the one shown below that are incorporated into the Javadoc.
{|
! Interface Name
! Stability Classification
! Specified in What Document?
|-
| ProviderRegistrationRemoval
| [http://openide.netbeans.org/tutorial/api-design.html#category-devel Under Development]
| [http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/doc-files/api.html#service-lookup api.html]
|-
|LookupAPI
|[http://openide.netbeans.org/tutorial/api-design.html#category-official Official]
|[http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/doc-files/api.html#lookup #lookup]
|-
|LookupSPI
|[http://openide.netbeans.org/tutorial/api-design.html#category-official Official]
|[http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/package-frame.html package-frame.html]
|-
|Set of property APIs
|Individual
|[http://www.netbeans.org/download/dev/javadoc/org-openide-util/architecture-summary.html#group-property table with definitions]
|}
====Setting up the infrastructure====
If you write a NetBeans module you may want to setup the right layout of files first. The default infrastructure ([http://www.netbeans.org/source/browse/~checkout~/nbbuild/templates/common.xml nbbuild/templates/common.xml] and [http://www.netbeans.org/source/browse/~checkout~/nbbuild/templates/projectized.xml nbbuild/templates/projectized.xml]) let you do various tweaks, but usually it is easier to just use the expected default layout (currently described in [http://www.netbeans.org/source/browse/~checkout~/apisupport/harness/README README]). The documentation related files shall be organized as follows:
<pre>
module_dir/src/ - directory with your sources
module_dir/src/**/package.html - description of each package
module_dir/src/**/doc-files/ - directory for special javadoc files
module_dir/arch.xml - answers to architecture questions (see bellow)
module_dir/apichanges.xml - description of the history of changes
module_dir/nbproject/project.xml - project file with dependencies and other informations
</pre>
The locations of arch.xml and apichanges.xml moreover has to be specified in [http://www.netbeans.org/source/browse/~checkout~/projects/projectapi/nbproject/project.properties nbproject/project.properties] as <tt>javadoc.arch=${basedir}/arch.xml</tt> and <tt>javadoc.apichanges=${basedir}/apichanges.xml</tt>.
====Writing the documentation====
# '''Generate arch.xml''' - open your project in NetBeans and select <em>Generate Architecture Description</em> from a context menu in projects tab. An empty, skeleton file will be generated. You can always reinvoke this target, if your answers are old, unanswered questions will be generated to the end of the file (the file shall stay well formated). When editing the file you can use <b>HTML tags</b>. <br><br>Some of the answers may have autogenerated default answers (currently arch-where and dep-nb) for cases where the information is already recorded anywhere else (for example in project.xml file). They may or may not be accurate. You can <b>accept</b> the generated answer while surrounding it with your additional comments or you can <b>suppress</b> it. Just include <code><defaultanswer generate='here' /></code> or <code><defaultanswer generate='none' /></code> in the answer of for your question. If you do not use the <code><defaultanswer/></code> element at all the default answer is <b>apended</b> to your own answer. If you generate the defaultanswer, the source code for it is put into the comments in the html file, so if you are not satisified with the defaults, you can easily copy the output modify it and <code><defaultanswer generate='none' /></code>.
# '''Use <api/> tag''' - this tag is one of the most important in the architecture file. Each use of the <api> tags generates new item into a table of API interfaces. This is the main entry point to the documentation, so use the tag a lot. Not just for a description of javadoc interfaces, but for everything. Remember that an api is [APIDesign|any feature that someone else rely on]. Describe DTDs, properties, files or layers you read, formats or protocols that you communicate, etc. The <tt><api/></tt> tag syntax is described by its DTD and consists of:
#: '''name''' - the name of the API, DTD or property
#: '''group''' - the group that this API belongs. For example "property", "java", "dtd", "layer" and possibly others. As we are writing in java the attribute can be omitted and the default value is "java".
#: '''type''' - you can either use someone else API ("import") or offer someone else dependency on your behavior ("export").
#: '''category''' - shall contain a name from the enumeration (<tt>official</tt>, <tt>stable</tt>, <tt>devel</tt>, <tt>third</tt>, <tt>standard</tt>, <tt>friend</tt>, <tt>private</tt>, <tt>deprecated</tt>) in the meaning described [[APIDesign#categories|here]].
#: '''url''' - shall refer to a document describing the API, if available otherwise one can insert additional comments into the body between the <tt><api></tt> and <tt></api></tt>.
#: An example is available here:<br/><tt><api name="identification" group="dtd" type="import or export" category="stable" url="where is the description" >Possibly some additional description to the API which may be skipped. </api></tt><br/>The interfaces in the table are grouped by the group of the API and marked in the HTML text as <tt><a name="group-name" /></tt> so a reference to these tables can be made by using <tt><a href="#group-name" /></tt>.
# '''Use <usecase> tag''' - when answering "arch-usecases" question, surround the paragraphs describing the way to use your API with <tt><usecase name="..." id="..."></tt> and <tt></usecase></tt>. That way your paragraph will get correct heading in the [http://www.netbeans.org/download/dev/javadoc/usecases.html How to use certain NetBeans APIs] page.
# '''Answer "arch-what"'''' - the first sentence of your answer to "arch-what" is used as a short description in the [http://www.netbeans.org/download/dev/javadoc/overview-summary.html overview page] so write it meaningfully. The full answer is then used in [http://www.netbeans.org/download/dev/javadoc/overview-summary.html#def-api-Terminal%20Emulator the details] section, so again, make it real and useful description of your module.
# '''Link between documents''' - important part of documentation is the description of context. It is not enough to say: "find this interfacein lookup". The reader may not know what "lookup" is, so it is better to hyperlink to its definition. You can use regular <tt><a href></tt> tag to link to other documents, for root of your javadoc use '''@TOP@'''. So link to lookup would be <tt>@TOP@/org/openide/util/Lookup.html</tt>.
# '''Link between classes''' - consider making the prose section part of <tt>package.html</tt> file. Then you can use '''@{link classname}''' to address any class of your module or from modules you depend on.
# '''Link between Javadoc sets''' - the context is often split between multiple modules. To allow links between them, the root of each module javadoc can be referred to as '''@org-netbeans-the-module-code-base-name@'''. So to link to lookup from another module one can use <tt>@org-openide-util@/org/openide/util/Lookup.html</tt> (the list of all currently known module name substitutions is available at [http://www.netbeans.org/source/browse/~checkout~/nbbuild/javadoctools/replaces.xml?content-type=text/plain nbbuild/javadoctools/replaces.xml]).
# '''Use Relative Links''' - please remove as much as possible of usages of non-relative links like http://www.netbeans.org/download/dev/javadoc and replace them with '''@TOP@''', '''@org-netbeans-module-name@''' or '''@JDK@''' root points. The javadoc is being scanned for allowed and disallowed links (defined in [http://www.netbeans.org/source/browse/nbbuild/javadoctools/disallowed-links.xml nbbuild/javadoctools/disallowed-links.xml]) and violations cause the build run from IDE to fail. It is generally not recommended to refer to NetBeans website as the documentation shall be self contained, but if you find a URL that makes sence, feel free to add it to the [http://www.netbeans.org/source/browse/nbbuild/javadoctools/disallowed-links.xml nbbuild/javadoctools/disallowed-links.xml] yourself. Btw. it seems better to use such pseudo root point than directly relative link as for example content of package.html is usually duplicated into more directories.
# '''Create apichanges''' - important part of any api is history of its changes. That is why create and maintain the [http://www.netbeans.org/source/browse/~checkout~/openide/loaders/api/apichanges.xml apichanges.xml] as described in NetBeans [[VersioningPolicy]]. When you refer to a class that no longer exists inside an API change, you can use <tt><class ... link="no"/></tt>.
# '''Validate your documentation''' - make sure the documentation format is correct (links point to valid places, XML files has valid syntax, etc.). This can be checked by invoking "Generate Javadoc" from the context menu. This builds the Javadoc and (in addition to invoking <code>ant javadoc</code> from command line) also checks for broken links and fails if there any - so make sure all Javadoc of modules you are referring to has already been generated.
====Publishing Javadoc====
All NetBeans project Javadoc sets are being daily regenerated and uploaded to the central [http://www.netbeans.org/download/dev/javadoc/ NetBeans API List]. When your module can successfully build javadoc as described in previous section, it is time to consider adding it to the API list as well. <br/><br/>To add it, you have to modify [http://www.netbeans.org/source/browse/nbbuild/build.properties.diff?r1=1.261&r2=1.262 nbbuild/build.properties] and add own module into <tt>config.fixedmodules.javadoc</tt> property. Use<pre>
ant -f nbbuild/build.xml check-module-configs
cvs -q diff nbbuild
</pre>
to review your changes. Then verify that everything works correctly by rebuilding all Javadoc:
<tt>ant -f nbbuild/build.xml build-javadoc</tt> <br/><br/>and if the build succeeds and really contains your module, prepare for committing your changes into CVS (check in the new <tt>moduleconfigs.txt</tt> too). Please note that three files in <tt>nbbuild/javadoctools</tt>
shall be modified by addition of references to your module root. Verify that the additions are sane (e.g. contain no local references and look like the other lines in the files) and then commit the modified
[http://www.netbeans.org/source/browse/nbbuild/build.properties.diff?r1=1.261&r2=1.262 nbbuild/build.properties], [http://www.netbeans.org/source/browse/nbbuild/javadoctools/replaces.xml.diff?r1=1.3&r2=1.4 nbbuild/javadoctools/replaces.xml],
[http://www.netbeans.org/source/browse/nbbuild/javadoctools/links.xml.diff?r1=1.2&r2=1.3 nbbuild/javadoctools/links.xml] and
[http://www.netbeans.org/source/browse/nbbuild/javadoctools/properties.xml.diff?r1=1.2&r2=1.3 nbbuild/javadoctools/properties.xml].
====Javadoc Tips====
By default the basic overview page is generated based on content of your [http://www.netbeans.org/source/browse/~checkout~/apisupport/project/arch.xml arch.xml],
[http://www.netbeans.org/source/browse/~checkout~/java/project/apichanges.xml apichanges.xml]
and [http://www.netbeans.org/source/browse/~checkout~/java/project/nbproject/project.xml project.xml].
To see an example, check the [http://www.netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/overview-summary.html overview page of component palette api].
This page has following structure:
# '''Title and description''' is taken from the <tt>arch.xml</tt>'s answer to question <tt>arch-overall</tt>.
# '''List of javadoc packages''' is added by the default javadoc doclet.
# '''what is new section''' lists five recent api changes listed in <tt>apichanges.xml</tt>. Always add at least one change as this document is used to generate what is [http://www.netbeans.org/download/dev/javadoc/apichanges.html new for the whole release].
# '''List of usecases''' is taken from the <tt>arch.xml</tt> answer to <tt>arch-usecases</tt> question. It shall contain the main introduction into the meaning and usage of the API. Links to javadoc classes and methods are welcomed. Also notice that the answer contributed to [http://www.netbeans.org/download/dev/javadoc/usecases.html global page with usecases] for all NetBeans APIs.
# '''Implementation details''' close the summary page. The contain answer to <tt>arch-where</tt> question, which shall contain link to NetBeans WebCVS with the module sources like http://www.netbeans.org/source/browse/~checkout~/java/project/ for the [http://www.netbeans.org/source/browse/~checkout~/java/project/ java/project] module. Also an answer to <tt>deploy-dependencies</tt> arch question is generated so other modules know how to express dependency on this one.
'''XXX''' need to describe: <tt>{@link ...}</tt>, what <tt>package.html</tt> can and cannot do, <tt>@inheritDoc</tt>, etc.
===Reviewing APIs===
In order to ensure good enough quality of produced APIs there is a service provided to module writers - they can ask for an API review.
It is required that every new API will be reviewed prior to integration into trunk. The exception from this rule is a <tt>friend</tt> API that is used only by modules within the same cluster (the module has to explicitly list its friends). In this case the review is recommended but not required.
====Why?====
The short answer to question why you should be interested in an architecture review is "because it will be useful". Useful to you, as you discover new possible solutions to your problems or mistakes in your design, that might appear later, when integrated together with the whole system or even in later versions, when problems with maintainability and extensibility can show up. It will be useful to the whole system as it will be composed from more stable components integrated in better ways. It will be useful to whole your project as it will get better.
Nobody knows everything, but there is a lot of knowledge spread around. Architecture review is a way to get the people with pieces of knowledge together and cooperate in preventing us from repeating known mistakes and solving problems in the wrong way.
Ask for advice through architecture review. It cannot hurt and it is likely going to be useful.
====What?====
It is unlikely that the review team will do some coding for you. It is also unlikely that the reviewers are going to become domain experts and help you understand your users or your requirements. This is your task and you have to prepare these materials for the reviewers, as it is very likely they will ask you about these questions in order to verify that your way of solving problems of your users is really the right one.
As a result of architecture review you can expect advices and help in identification of
* [[APIDesign#api|apis] that someone else could depend on,
* design or implementation that might have performance problems,
* influences of your solution on existing products or
* influences of other products on your solution in future,
* solutions that are solving something different than was the original goal and
* other projects or efforts going around that might help you in solving your problems.
More or less expect "just" a high level help.
====When?====
Whenever you need architecture advice or clarification and because the charter of the team is mostly high level, it is reasonable to come for the initial opinion as soon as the architecture is visible so it can be reviewed. This usually means after answering the first (more general) set of the architecture questions which should be done before the actual start of implementation. At this point the high level advices are of some use, later it is always hard to change implementation that has been written.
Of course things are likely change during implementation, but the high level direction given during this ''inception'' stage are likely not going to be questioned then and only the newly discovered facts and differences from the original suggestions are going to be evaluated during the ''before-commit'' review.
====How?====
For details about the process see the Architecture Review Steps document or check the list of all reviews.
===Testing APIs===
====Why?====
If an API is supposed to stand the test of time it has to preserve the functionality that others are using, it has to be backward compatible. Some tests for compatibility are easy, some require more work, but the testing is necessary otherwise nobody can guarantee quality when the API is evolving.
[[#sigtests|Signature tests]] are simple starting point, [[#unittests|unit tests]] are very good for verifying the "contract" between a public API and its clients. Some people claim that unit tests are poorly named since they imply that they are QA's responsibility, but the development engineer is the one that really
benefits with several advantages:
* the tests provide an example of how the developer expects the API to be used.
* Another is that when you run code coverage against a unit test suite, it shows surprising areas where there is code that isn't necessary to support the API, so one can easily remove those extra bits
* Another interesting feature of unit tests is support of arrogance (which is part of all good programmers). So here's the best, most compelling reason for creating and relying on unit tests: you can much more confidently tell another engineer how wrong he is when he claims your code is breaking his!
Read more about possible test patterns that we use and how they can contribute to improvements in quality of your module.
====Signature Tests====
There is an automated verification task that is executed after every daily build that checks signature of classes and their fields and methods and sends reports to [http://netbeans.org/projects/www/lists/api-changes/archive api-changes] mailing list. Its reports contain both incompatible and compatible changes. So one gets notified not only when something is broken, but also in case of accidental API change like addition of a method by forgetting to make it
<tt>private</tt>.
By default the tests check all classes in [[APIDesign#category-official|official]] packages. E.g.
<tt>org.openide.*</tt>, <tt>org.netbeans.api.*</tt> and <tt>org.netbeans.spi.*</tt> and recently also <tt>org.netbeans.jmi</tt> that are part of modules included in daily build of standard IDE and also those that are daily uploaded to <em>Alpha Update Center</em>. That is why in order to have these tests running on own module one has to package the API into one of the official package (or
[mailto:nbdev@netbeans.org request] his own package to be added into the test) and make the module part alpha autoupdate configuration.
Any questions related to the sigtest framework can be either sent to [mailto:nbdev@netbeans.org nbdev@] or to [mailto:rbalada@netbeans.org Rudolf Balada] who maintains the daily build (including sigtest) infrastructure.
====Unit Tests====
Very important verification of quality of an API is an automated test suite. Most of NetBeans modules uses our test harness called [http://xtest.netbeans.org xtest] which is based on [http://www.junit.org JUnit] and enhances it with a few additional features (tests should inherit from [http://www.netbeans.org/source/browse/~checkout~/xtest/nbjunit/src/org/netbeans/junit/NbTestCase.java NbTestCase]) and configuration framework.
The simplest way how to make your module testable is to copy the <tt>test</tt> directory from a small modules that already provide some tests and modify it (e.g. [http://www.netbeans.org/source/browse/html/test/ html]). The needed changes include classpath modifications for compilation and execution in <tt>build.xml</tt>, correcting the list of tests in
<tt>cfg-unit.xml</tt> and of course the placing your own tests into <tt>unit/src</tt> directory.
The last step is to include the suite in daily execution of unit tests. For that it is enough to modify the
[http://www.netbeans.org/source/browse/~checkout~/xtest/instance/master-config.xml xtest/instance/master-config.xml] to include your module in the '''unit-nb''' test config. Verify that you have done everything correctly by running<pre>ant -f nbbuild/build.xml unit-validation</pre>
and checking that your tests were successfully executed. Since then make sure that your module tests really run and pass, as since then other people start to use these tests to verify validity of their own commits. And you should not cause false alarms by problems in your code.
Also consider to subscribe to [http://beetle.czech:8080/unittest/ notification framework] to get email notifications about automatic failures, if you can reach the URL.
===Deploying the APIs===
The important part in a [[APIDesign#life|life cycle]] of an API (as well as any other product) is the feedback from the users. In order to get it one should let your users know that there is an API and allow they to try it. For that purpose NetBeans use its "Alpha Update Center". Curious users may enable it and
that way be informed about latest development achievements.
To get a module into the "Alpha Update Center" one needs to make sure that the module's <tt>build.xml</tt> file has <tt>netbeans</tt>, <tt>clean</tt>, and <tt>nbm</tt> targets that work in the normal way - normally this is accomplished trivially by making a projectized module and not overriding any targets from the default build harness.Then one can add entries for the new module to <tt>nbbuild/build.properties</tt> in the list <tt>config.modules.daily-alpha-nbms</tt>. Use<pre>
ant -f nbbuild/build.xml check-module-configs
cvs diff ide/golden/moduleconfigs.txt
</pre>to review your changes (check in the new <tt>moduleconfigs.txt</tt> too).
<br/>
One should test the NBM building process on local disk by making sure you have everything of interest checked out from CVS, opening <tt>nbbuild</tt> as a project in the IDE, and selecting '''Build Daily Alpha NBMs''' from its context menu. If something is messed up, mail gets sent to <tt>broken_builds@netbeans.org</tt> so it can be corrected. It is a good idea to notify
[mailto:aumasters@netbeans.org?subject=FYI:%20adding/updating%20daily%20alpha%20NBMs <tt>aumasters@netbeans.org</tt>] too.
====Publishing New Versions====
The content of "Alpha Update Center" is refreshed every day. The new version of module NBM is build from trunk and specification version in its module manifest is compared to the specification version of already uploaded module. If the new one is greater, the new version of the module replaces the old one.
This means that one can consciously and automatically upload new versions of an API from trunk to its users just by increasing the specification version in the CVS manifest file.
===Stabilize the APIs===
Usually an attempt to produce an API requires longer development time and it is useful to mark it as not being finished yet. NetBeans use a set of [[APIDesign#life|stability categories] for that.
The expected scenario is that a module with an API starts its development in a CVS sandbox ([http://www.netbeans.org/community/contribute/modules.html contrib.netbeans.org]) or as a regular '''netbeans.org''' project (like [http://xml.netbeans.org xml.netbeans.org]) but is not part of the regular build. Then it is offered on Alpha or Beta AutoUpdate (early access mode) and one can work on its finalization. As the module is not part of a stable release, it can be modified in incompatible way. As soon as one thinks that the API is fine and it satisfies [http://qa.netbeans.org/processes/stabe_module_criteria_process.html quality criteria], it can be put on "Stable Update Center" or even find its way into standard distribution.
====Official APIs Restrictions====
There is however one restriction. In order to make it easy for API users to find out what is stable API we have come with a simple description: "If a class is in <tt>org.netbeans.api.*</tt> or <tt>org.netbeans.spi.*</tt> packages, and is part of a stable release, then it is [[APIDesign#category-stable|stable]]". Such API is then called NetBeans [[APIDesign#category-official|Official]] API.
This rule is not meant to block anyone in producing APIs. One can always create an API in less prominent package (say [http://www.netbeans.org/download/dev/javadoc/#def-api-ant org.netbeans.modules.ant.api]), publish it on netbeans.org as [[APIDesign#category-stable|stable]] one and use all the infrastructure for API development that is available. Moreover this approach is not as strict and allows the API to be part of a release even if it has not reached enough stability for unlimited amount of time.
====Support for Early Adoption====
There can be situations when strictly following the "official namespace restriction" may cause a lot of troubles to early adopters and hurt NetBeans acceptance and competitiveness. Sometimes one needs to provide an API quickly, cannot guarantee that it is that [[APIDesign#category-stable|stable]], but is strongly willing to stabilize it in <em>close future</em>. In such case it may be acceptable to release the API in official packages, mark it as [[APIDesign#category-devel|under development]] (by warning in javadoc and special name of the module) and stabilize it in next release. In such cases it may be possible to allow a temporary release of an API [[APIDesign|under development]] in official namespace if following is guaranteed:
* the API is intended to become [[APIDesign#category-stable|stable]]
* making it [[APIDesign#category-stable|stable] has been agreed to be the highest priority for next release
* the API is of "nearly stable" quality - documented, tested, published and successfully reviewed
The purpose of this "temporary release" is to encourage early adopters to test the APIs in real world and provide feedback to make them better. The publishers of the APIs in return promise to stabilize them soon and do that carefully considering the user impact. As a result NetBeans should be able to deliver important APIs as soon as possible, offer them to early adopters and increase API quality by incorporating the feedback. The adopters could be sure that the APIs will be stabilized in a given time frame and that they will not need to do major changes (like repackaging of all import statements, which was the current strategy) when the API becomes stable. In order to clearly communicate the exceptional state of the APIs, there should be a visible and non-ignorable stamp that such APIs are [[APIDesign#category-devel|under development]]:
* the javadoc documentation headers shall contain visible warnings
* the module name shall indicate that it is not stable yet. This shall be done using "/0" in module name, for example <tt>org.netbeans.api.projects.ant/0</tt>. As this string has to be used by every module writer to specify module dependency it forms appropriate warning. When stable version of the module is produced and is incompatible with the "/0" version, the name should change to <tt>org.netbeans.api.projects.ant/2</tt>. If the stable version remains compatible the name of the module should be <tt>org.netbeans.api.projects.ant/1</tt> and appropriate [http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#refactoring ModuleAutoDeps] shall be provided to upgrade dependencies of modules that used the "/0" version.
These suggestions shall ensure that the right balance is achieved between produces and consumers of any NetBeans API. It should however be stated that nobody shall be restricted by "Official namespace restriction" or bound by a time limit of the "temporary release", because if one does not want to create stable API, one does not have to. Contributing to [[APIDesign#category-official|official]] API set shall be a privilege as such effort requires more attention and increased amount of work that only those who really care are willing to invest.
{{information|Comments or corrections to [mailto:nbdev@netbeans.org nbdev@netbeans.org] or [mailto:apireviews@netbeans.org apireviews@netbeans.org].}}