| Name | Metadata Plugin 2 |
|---|---|
| Vendor | Andy Armstrong |
| Authors | Andy Armstrong, Kelsey Grant |
| Homepage | http://confluence.atlassian.com/display/CONFEXT/Metadata+Plugin |
| Issue Management | http://developer.atlassian.com/jira/browse/META |
| Continuous Integration | n/a |
| Categories | Content Macros |
| Most Recent Version | 2.1.0 |
| Availability | Confluence v2.7 to v2.10 |
| State | Stable |
| Support |
|
| License | Freeware / Open Source (BSD) |
| Price | Free |
| Release Docs | http://confluence.atlassian.com/display/CONFEXT/Metadata+Plugin |
| Java API Docs | n/a |
| Download Source | http://svn.atlassian.com/svn/public/contrib/confluence/metadata-plugin/tags/2.1 |
| Download JAR | metadata-2.1.0.jar |
| This plugin now accessible through the Confluence Repository Client. |
| This documentation has not yet been updated for version 2.0. The new features are described as part of the Codegeist submission. |
This extension won an honorable mention in Atlassian's Codegeist competition for 2006.
Description/Features
This plugin allows the user to attach metadata to any page in Confluence and to then generate reports and statistics using it.
The largest problem that we've had using Confluence at Pantero is that information has to be replicated on multiple pages. For example, it is extremely common to repeat information from a number of pages onto a summary page. The children and contentbylabel macros allow a page to reference a set of related other pages, but these summaries are restricted to just a link to the page and optionally an excerpt. I found myself instead manually building these summary tables but they quickly get out of date.
I strongly believe that data should only live in one place and that other pages that need to show the same information should reference the data rather than copy it. I decided to write a plugin that makes it easy to reference snippets of data from one page on other pages. The Metadata Plugin can generate these summary tables automatically to contain as many columns of metadata per page as make sense. In fact, multiple pages can now present the same list but with more or less detail as appropriate. See the examples for more details.
In some ways, what I've implemented is a glorified 'excerpt' macro. Instead of there being just a single magic excerpt, though, the user can create as many pieces of metadata as they like. There are two basic macros for adding metadata to a page:
- metadata - lets the user add a single piece of metadata
- metadata-list - allows the user to enter a number of values at once
The remainder of the macros are provided to present metadata data on other pages. The simplest of these, metadata-from, shows a single metadata value from a specified page. The more interesting macros are those that aggregate data from a number of sources to dynamically build up tabular reports, dashboards, charts and other useful statistics. In some ways these macros treat Confluence like one giant Excel spreadsheet where data can be gathered from anywhere and presented.
In addition to the report macros, the Metadata Plugin provides two other ways to access the metadata. Firstly, all metadata is indexed and can be searched by keyword. Secondly, an experimental remote API has been provided so that the metadata can be accessed by other applications.
Usage
The plugin provides the following new macros:
| metadata | Saves metadata to the page to be referenced from other pages. |
| metadata-list | Saves a list of metadata values to the page. |
| metadata-from | Shows a metadata value from another page. |
| metadata-report | Shows a tabular report of metadata from matching pages. |
| metadata-calculate | Performs a calculation across all matching metadata values. |
| metadata-total | Totals up a metadata value from matching pages. |
| metadata-matches | Returns the number of matching pages whose metadata matches the macro's body. |
metadata macro
The basic macro lets you attach a single piece of metadata to a page.
{metadata:Author}[~andy.armstrong]{metadata}
would render simply as:
but would also attach "Author" as a piece of metadata to the page. Note that the metadata is stored as unrendered Wiki markup, so in this case the value "[~andy.armstrong]" is stored for the "Author" metadata. The reporting macros then render the markup into the page they are used on. This usually works very well because links, emoticons etc can be used.
If you don't want the metadata on the page you can use the "hidden" parameter.
{metadata:Author|hidden=true}[~andy.armstrong]{metadata}
metadata-list macro
This macro allows the user to attach multiple pieces of metadata to a page with one macro. The main purpose of this is to make it allow a user to add metadata more concisely and to make the Wiki markup easier to read.
The following usage:
{metadata-list}
|| Name | Metadata Plugin |
|| Version | 1.0 |
|| Product Versions | Confluence 2.x |
|| Author(s) | Andy Armstrong |
{metadata-list}
adds four pieces of metadata to the page, as well as rendering the following output:
| Name | Metadata Plugin |
|---|---|
| Version | 1.0 |
| Product Versions | Confluence 2.x |
| Author(s) | Andy Armstrong |
An optional orientation=horizontal parameter changes the rendering to be horizontal. It will then render as follows:
| Name | Version | Product Versions | Author(s) |
|---|---|---|---|
| Metadata Plugin | 1.0 | Confluence 2.x | Andy Armstrong |
metadata-from macro
This is the simplest macro to get a piece of metadata from another page onto the current one.
The Metadata Plugin was written by {metadata-from:Metadata Plugin|Author}.
would pull the 'Author' metadata from the 'Metadata Plugin' page and hence would show as:
The Metadata Plugin was written by Andy Armstrong.
The Metadata Plugin was written by {metadata-from:Author}.
pulls the 'Author' metadata from the current page.
metadata-report macro
This macro shows metadata from matching pages in a tabular report. By default it shows the children of the current page, but it has an optional label attribute to match all pages with the specified label.
The basic format is:
{metadata-report:Page,Author(s),Version}
would then show the following table (assuming two children):
| Page | Author(s) | Version |
|---|---|---|
| Metadata Plugin | Andy Armstrong | 1.0 |
| [Another Plugin] | Joe | 2.1 |
To show a table of all pages with the 'codegeist' label you can instead use:
{metadata-report:Page,Author(s),Version|label=codegeist}
Note that "Page" is an 'internal' metadata keyword that produces a link to the page in question. Internal keywords have lower priority than explicit metadata values but are provided for convenience. See the list of internal metadata for more details.
The report can provide totals for certain columns using the totals argument. Say that each entry had a number of lines of code stored under "LOC", then this would show the totals:
{metadata-report:Page,Author(s),Version,LOC|label=codegeist|totals=LOC}
| Page | Author(s) | Version | LOC |
|---|---|---|---|
| [Another Plugin] | Joe | 2.1 | 300 |
| Metadata Plugin | Andy Armstrong | 1.0 | 500 |
| Totals | 800 |
Finally, the macro allows the report to be sorted in different orders. The default ordering is by page, but a sort=XXX parameter can be specified.
{metadata-report:Page,Author(s),Version,LOC|label=codegeist|totals=LOC|sort=LOC desc}
| Page | Author(s) | Version | LOC |
|---|---|---|---|
| Metadata Plugin | Andy Armstrong | 1.0 | 500 |
| [Another Plugin] | Joe | 2.1 | 300 |
| Totals | 800 |
metadata-calculate macro
This macro returns a single value by totalling up any float or integer metadata. This result can be shown directly or can be used as input to another statistics macro.
The simplest example is to include a single total on the page.
We have {metadata-calculate:Days Remaining} days remaining.
which then shows as:
We have 800 days remaining.
This macro is more useful to present several totals in a single chart. For example, the following Wiki markup will produce a chart showing the number of days remaining in a set of releases:
{chart:title=Days remaining per release|width=500|height=200|dataOrientation=horizontal}
|| || 2.1 release || 2.2 release ||
|| Days Remaining
| {metadata-calculate:Days Remaining|label=2_1_release}
| {metadata-calculate:Days Remaining|label=2_2_release} |
{chart}
An optional function argument can be specified to control how the resulting number is calculated. This can be any of the following values:
| Sum | Returns the sum of each non-empty value (default) |
|---|---|
| Average | Returns the average of each non-empty value |
| Minimum | Returns the minimum of each non-empty value |
| Maximum | Returns the maximum of each non-empty value |
metadata-matches macro
This macro totals up the number of matching pages which have a particular value for metadata. This result can be shown directly or can be used as input to another statistics macro.
Here's an example bar chart that can be produced by using metadata-matches within a chart macro.
{chart:type=bar|title=Release Status|width=500|height=200|orientation=horizontal}
|| || Tasks ||
|| Delayed | {metadata-matches:Status}Delayed{metadata-matches} |
|| In Progress | {metadata-matches:Status}In Progress{metadata-matches} |
|| Complete | {metadata-matches:Status}Complete{metadata-matches} |
|| Not Started | {metadata-matches:Status}Not Started{metadata-matches} |
{chart}
You can also see the same metadata in a pie chart:
{chart:title=Release Status|width=500|height=200}
|| || Delayed || In Progress || Complete || Not Started ||
|| Issues | {metadata-matches:Status}Delayed{metadata-matches}
| {metadata-matches:Status}In Progress{metadata-matches}
| {metadata-matches:Status}Complete{metadata-matches}
| {metadata-matches:Status}Not Started{metadata-matches} |
{chart}
In addition, this macro allows for another metadata value to be calculated for each matching page. The following syntax will total up all of the days remaining on features for which I am assigned:
{metadata-matches:Owner|labels=2_2_new_feature|value-name=Days Remaining}
[Andy Armstrong]{metadata-matches}
By default this sums the values, but the same function parameter can be used as with metadata-calculate.
Using this mechanism you can produce bar charts showing how a particular value is broken down. Currently this is very manual so a new metadata-chart macro is currently being considered. In the interim this manual code:
{chart:type=bar|title=2.2 Release Load Balancing|orientation=horizontal}
|| || Andy Armstrong || David Dahan || Esther Jesurum || John Avery || Maya Dahan ||
|| Days Remaining
| {metadata-matches:Owner|labels=2_2_new_feature|value-name=Days Remaining}
[Andy Armstrong]{metadata-matches}
| {metadata-matches:Owner|labels=2_2_new_feature|value-name=Days Remaining}
[David Dahan]{metadata-matches}
| {metadata-matches:Owner|labels=2_2_new_feature|value-name=Days Remaining}
[Esther Jesurum]{metadata-matches}
| {metadata-matches:Owner|labels=2_2_new_feature|value-name=Days Remaining}
[John Avery]{metadata-matches}
| {metadata-matches:Owner|labels=2_2_new_feature|value-name=Days Remaining}
[Maya Dahan]{metadata-matches} |
{chart}
produces the following chart:
Macro keywords
The following is a summary of all the keywords supported by the Metadata Plugin macros:
| Keyword | Description | Used By |
|---|---|---|
| function | Specifies the function to apply to the matching data (default: sum) | metadata-calculate |
| hidden | Specifies that the metadata value won't be rendered | metadata, metadata-list |
| key | Limits the content returned to be within the space with the given key | metadata-report metadata-calculate metadata-matches |
| labels | Limits the content to only that which has the specified label(s). A comma separated list produces ANY pages that match, while using '+' will give ALL pages. Parentheses may be used to build up complext expressions, e.g |labels=(yellow,red)+fruit | metadata-report metadata-calculate metadata-matches |
| root | Specifies a set of pages to include. When used in combination with the 'pages' option, allows children of a particular page. Use @self for the current page (the default), @parent for the parent page, or the name of any page, e.g MySpace:MyPage. If this is specified and the pages option is not, then the report will run over only the pages listed here. | metadata-report metadata-calculate metadata-matches |
| pages | Specifies a set of pages to grab from the root page(s). Supports @children, @ancestors, @descendants, @ancestors. For example, |root=@self|pages=@children will give all children of the current page. This can be used in combination with the labels option to find all children with a particular label. | metadata-report metadata-calculate metadata-matches |
| link | Specifies which columns in the report should link back to the content | metadata-report |
| maxResults | Specifies the maximum number of results in a report (default: 500) | metadata-report |
| orientation | orientation=horizontal makes a report horizontal | metadata-list |
| sort | Specifies which columns in the report should be sorted by (e.g. "Status desc") | metadata-report |
| totals | Specifies a comma separated list of values to be totalled. | metadata-report |
| type | Specifies which Confluence content types should be considered for a report. This feature was based on the 'contentbylabel' macro which has the same attribute. See this page for (some) details:http://confluence.atlassian.com/display/CONF20/Content+by+Label+Macro |
metadata-report metadata-calculate metadata-matches |
| value-name | The metadata value that will be used for a calculation. | metadata-report metadata-calculate metadata-matches |
Metadata search
The Metadata Plugin provides a search extractor that will add each piece of metadata to the Confluence index. For example, you can make the query:
Author:Andy
which will return all pages that contain "Andy" in their author metadata. You can then combine this with other search syntax to do sub-searches.
Remote API
New in version 1.3 a prototype remote API has been implemented. Currently just one method has been provided:
/** * Returns all of the metadata values attached to the specified page. * @param token The token identifying the current user. * @param spaceKey The key of the space that the page belongs to. * @param pageName The name of the page. * @return An array of MetadataValue objects. * @throws RemoteException if the page cannot be found. */ MetadataValue[] getMetadataValues(String token, String spaceKey, String pageName) throws RemoteException;
MetadataValue is a simple bean that provides 'name' and 'value'.
This API has been exposed as secure XML-RPC and SOAP services. See the Confluence Remote API Specification for examples of using such a service.
Examples
Pantero uses the Metadata Plugin in a number of ways to make its Wiki content more dynamic. Some examples include:
| Employee information | Each employee has a home page in Confluence which records all of their contact information such as work phone, cell phone, IM handles etc. A central contact info page then generates a report with all this information in one place. |
|---|---|
| New feature development process | When planning a new release we create a new page for each new feature under consideration. This page then links to separate pages for requirements, use cases, designs, implementation plans and test plans. All of this information is recorded in metadata to automatically produce executive dashboards. |
| Customer relationship management | Each customer has its own page as does each project we work on. Once again, this can then be aggregated in different ways depending on the audience. |
| Writing test plans | Every test plan that we write is labeled with 'testplan' and has its status registed in metadata. We then generate status pages that show us the overall testing status of our release. See Brian Sensale's Testplan Plugins) for help with this automation. |
| Software licenses | Each piece of software we purchase has a Confluence page dedicated to it, and then a complete audit of all licenses can be generated. |
There are all sorts of other kinds of structured data that could be usefully aggregated with the right combination of labels and metadata. Here are some we are considering:
- status reports
- meeting notes
- online documentation
- FAQs, tips and tricks, best practices etc
- sales leads
Version History
| Version | Date | Description |
|---|---|---|
| 1.5 | 07/25/2006 | Includes:
|
| 1.4 | 04/24/2006 | Includes:
|
| 1.3 | 03/17/2006 | Includes:
|
| 1.2 | 02/28/2006 | Includes:
|
| 1.1 | 02/28/2006 | Includes:
|
| 1.0 (patch) | 02/14/2006 | Fix metadata-list to trim metadata names and values |
| 1.0 | 02/13/2006 | Initial version. |
Screenshots
Issues/Ideas
This section describes some of the issues that arise using this plugin.
Metadata templates
How can I access non-metadata in my reports?
All the macros support certain built-in metadata names for internal data structure:
| Excerpt | Returns the page's excerpt |
|---|---|
| Page | Returns a link to the page |
| Parent | Returns a link to the page's parent |
| Space | Return's the page's space key |
| Title | Synonym for Page |
It is straightforward to add more so let me know what else you'd like to see.
Why wouldn't I use JIRA for this kind of data?
This is a good question and is a best practice that we're trying to develop as happy users of both JIRA and Confluence. JIRA is excellent for issue tracking because of its formal semantics and its clear workflow model. Confluence is better for ad-hoc data because metadata can be attached to a page and then used in reports without any administrative changes. Confluence also works better for living documentation due to its Wiki nature (attaching images, designing the look of the page etc).
Shouldn't project planning be done in Microsoft Project (or equivalent)?
For large or formal projects a real project planning tool is probably a good idea. For small startups that already have Confluence (like Pantero) it is preferable to have a looser project plan that is more tightly integrated with technical documentation, proposals, meeting notes etc.
Reported issues
Here is the list of open issues reported against the Metadata Plugin. Please feel free to report bugs or propose improvements.


Comments (180)
Mar 01, 2006
Russell Warren says:
I've got a case where I have a main page that has a {metadata-report} macro, and...I've got a case where I have a main page that has a {metadata-report} macro, and various child pages that are generic forms/templates with a set of metadata at the top. What I would like is for the generated report to be able to have column that contains links to the relevant child page. ie: the metadata-report summary contains blurbs of summary info from the various child pages, but I want to be able to link to the child pages from the appropriate summary table row.
How do I do this? Even if I make/find a "link to self" macro to put in as metadata, the data is passed on as unrendered markup so it doesn't help me. I don't want to have to have users repeatedly have to remember to enter the particular metadata field as a link of the page name they are working on.
I think that one nice implementation would be to tweak the metadata-report implementation a little bit so that you can specify which bit of metadata you want to be a link to the page the data came from. Maybe an @ prefix on the column name to be a link?
eg:
{metadata-report:@Version, Release date, Released by, Brief description}would set up a report with the indicated columns containing data from all child pages, and the Version data would be links to the child pages the data came from, with the alias for the links being the "Version" metadata. In the event of the metadata being a link itself, override with the page link and make the [ and ] chars into literals (if you click it you can then get through to the link at the metadata source)
In the absence of this feature, is there some other solution? The "metadata = unrendered markup" aspect makes me think not, but it would be good to know.
I'm unsure this comment is the best place for this request/suggestion - if not, where is the best place?
Mar 01, 2006
Andy Armstrong says:
The current solution for this is that there are some 'magic' metadata names whic...The current solution for this is that there are some 'magic' metadata names which treat internal Confluence information as if it were metadata. There is one called 'Page' which I think will do what you want. I really thought I'd documented that, but it appears that I didn't. I'll go back and add a description now. For the record, here are the internal metadata names you can use.
One issue is that you can't rename the column so you are currently stuck with it being Page and/or Title. That is something I've been meaning to address, so if it is important to you I'll do so. I can also easily add new internal metadata names if there is anything else you need (someone suggested 'Parent' to me today).
Mar 01, 2006
Russell Warren says:
Great! This muscles the functionality in for now... nice formatting can come la...Great! This muscles the functionality in for now... nice formatting can come later.
What would be nice:
Oct 02, 2006
Osma Ahvenlampi says:
It would be very useful to also be able to use the document's last update time a...It would be very useful to also be able to use the document's last update time and author in the metadata reports. In particular I'm working on a report in which I'd like to sort the metadata-report by the metadata source documents' update times..
Oct 02, 2006
Andy Armstrong says:
Hi Osma, This would be very useful information, and it has been much requested....Hi Osma,
This would be very useful information, and it has been much requested. Please vote for the issue here:
http://developer.atlassian.com/jira/browse/META-13
Thanks,
Mar 13, 2006
John Bowen says:
Great plugin! Is there a way to access metadata in another space? If not, plea...Great plugin! Is there a way to access metadata in another space? If not, please consider this a vote for it!
Mar 16, 2006
Andy Armstrong says:
I thought that this would 'just work' but it clearly doesn't. I've reported it a...I thought that this would 'just work' but it clearly doesn't. I've reported it and hope to have a fix in version 1.3 which is due out in the next couple of days.
http://developer.atlassian.com/jira/browse/META-4
Mar 13, 2006
John Bowen says:
Also, it would be nice if formatting macros contained by the metadata plugin wou...Also, it would be nice if formatting macros contained by the metadata plugin would still display properly. For example:
{metadata:Section1}Section1: {info}This is more information.{info} {metadata}This displays on the page as:
Section1: {info}This is more information.{info}Is there a way to work around this issue (to make the {info} tag display properly)?
Mar 16, 2006
Andy Armstrong says:
This is an oversight on my part. I've mostly moved over to using metadata-list w...This is an oversight on my part. I've mostly moved over to using metadata-list which does correctly render inner macros, so I didn't notice that metadata itself had stopped doing so. So you should see that the following works correctly:
{metadata-list} ||Section2|{info}This is more information{info}| {metadata-list}I've reported this one too:
http://developer.atlassian.com/jira/browse/META-5
Mar 22, 2006
Andy Armstrong says:
This bug was fixed in the 1.3 release that is now available. Thanks for the rep...This bug was fixed in the 1.3 release that is now available.
Thanks for the report.
Mar 19, 2006
David Peterson [CustomWare] says:
Any chance of adding a '@self' and '@parent' option for {metadata-from}? That wo...Any chance of adding a '@self' and '@parent' option for {metadata-from}? That would make it easier to put self-referencing metatdata definitions into templates. For example, I'm using it to create a bibilographic reference list, and want to have a dynamically-build set of different reference styles (APA, Chicago, Harvard, etc) on the page, based on the author, publication date, title, etc on that same page. Eg:
|| Author(s) | {metadata:Author}Bloe, Joe{metadata} | || Publish Date | {metadata:Publish Date}2006{metadata} | etc... || APA || {metadata:APA}{metadata-from:@self|Author} ({metadata-from:@self|Publish Date}). etc...{metadata} |I can then get a list of nicely-formatted references in the style of my choice by pulling the 'APA' metadata content from all reference pages.
Oh, also, it would be handy to be able to define a section as only visible if a piece of metadata is non-null/non-blank. Eg, the following would only be visible if 'Subtitle' had a value:
{metadata-if:@self|Subtitle}Subtitle: {metadata-from:@self|Subtitle}{metadata-if}Mar 19, 2006
Andy Armstrong says:
Those are both great ideas, David. Could you report them here and I'll add the s...Those are both great ideas, David. Could you report them here and I'll add the support for the next release:
http://developer.atlassian.com/jira/browse/META
Mar 20, 2006
David Peterson [CustomWare] says:
Yeah, I did start adding them as issues but got distracted by other impending de...Yeah, I did start adding them as issues but got distracted by other impending deadlines. I have actually implemented them both rather hurriedly (need further testing to make sure nothing else broke). Will you be putting the source code into Atlassian's Subversion repo at any point?
Mar 22, 2006
Andy Armstrong says:
I do plan on putting the code into Subversion at some point. I now have access b...I do plan on putting the code into Subversion at some point. I now have access but I haven't spent the time to learn how to work with it.
In the meantime I'd be happy to integrate your changes into mine if you want to send them to me:
Andy.Armstrong@pantero.com
Thanks.
Mar 25, 2006
RefuX Zanzeenbarr says:
I filed CONF-2233 a year and a half ago and now thanks to you it is fixed! Cheer...I filed CONF-2233 a year and a half ago and now thanks to you it is fixed!
Cheers!
Apr 02, 2006
Jeremy Higgs says:
Hi Andy, Great plugin! I would really love to see page labels as other page "no...Hi Andy,
Great plugin! I would really love to see page labels as other page "non-metadata" that can be displayed with the macro.
Thanks,
Jeremy
Apr 02, 2006
Andy Armstrong says:
Hi Jeremy, That's a great idea. I've reported it in JIRA so I can track it: ht...Hi Jeremy,
That's a great idea. I've reported it in JIRA so I can track it:
http://developer.atlassian.com/jira/browse/META-16
Thanks,
Andy
Apr 03, 2006
Jeremy Higgs says:
Great! Another thing I'm interested in doing is generating a chart from all valu...Great! Another thing I'm interested in doing is generating a chart from all values of a particular piece of metadata. I thought this might be possible by wrapping a metadata-report call with a chart, but it doesn't seem to be working.
As an example, I might define a number of values for a piece of metadata called "Foo". I might then want to display the number of pages that have defined the metadata "Foo" and see all of the values ("Bar", "ABC", "DEF") and how many times they occur. I could use the metadata-matches macro in this case, but if I add a new value for "Foo", I'd have to update any existing charts.
Is there an easy way of doing this, do you think?
Apr 03, 2006
Guy Fraser says:
The metadata plugin would have to output it's chart using wiki notation rather t...The metadata plugin would have to output it's chart using wiki notation rather than HTML - from memory, plugins like the Chart plugin only parse wiki notation.
Apr 03, 2006
Dan Hardiker says:
I believe (and I stand to be correct) that although the innards of the chart is ...I believe (and I stand to be correct) that although the innards of the chart is indeed wiki notation, it's actually the rendered HTML that is parses. However the table it expects is a Confluence table, something in the following form:
I think the current problem could be caused by incompatable html which the chart cannot read - although thats a pure hypothesis.