Custom ID auto generation pattern.

Oxygen general issues.
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Custom ID auto generation pattern.

Post by xsaero00 »

I want to change ID auto generation features of DocBook. I want to support m a format like

Code: Select all


${ancestorID}.${localName}${position}
${ancestorID} - is the id of closest ancestor that have auto id generation enabled
${position} - is the position of the element within context of closest ancestor

I would like to keep the functionality provided by DocBook extension and just build on it but there seems to be no way to easily extend it, unless I copy DocBook extension sources and tweek it directly in files. Is this an acceptable approach? I am developing this for in company use; there should not be any license issues?
Radu
Posts: 9055
Joined: Fri Jul 09, 2004 5:18 pm

Re: Custom ID auto generation pattern.

Post by Radu »

Hi Mike,

We offer the Java sources for all the bundled frameworks for which Oxygen has special Author support in order to help you build or customize a specific framework. So there are no licensing issues.

The easiest way would be to extend the:
ro/sync/ecss/extensions/docbook/id/Docbook5UniqueAttributesRecognizer.java

and overwrite the method:

Code: Select all

ro.sync.ecss.extensions.docbook.id.Docbook5UniqueAttributesRecognizer.generateUniqueIDFor(String, AuthorElement)
You will have access to the AuthorElement which will also give you access to its parent and the parent has a list of child nodes so you can also compute the position of the child in the parent. The method returns the generated ID.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Re: Custom ID auto generation pattern.

Post by xsaero00 »

I prefer to leave provided code along for easier upgrading later and to keep jar down in size.

All I see

Code: Select all


protected String generateUniqueIDFor(String idGenerationPattern, AuthorElement element)
inside DefaultUniqueAttributesRecognizer but it uses GenerateIDElementsInfo class that is also used by DocbookConfigureAutoIDElementsOperation. So if I override the generateUniqueIDFor method I'll lose some of the functionality of GenerateIDElementsInfo. I can work around it by running it through GenerateIDElementsInfo.generateID and then through my custom method, but the DocbookConfigureAutoIDElementsOperation would not be changed, it will not have a new tooltip that details the format.

Anyways I think this approach will work. Thanks for all of the help. I did not notice at first that authorAccess in DefaultUniqueAttributesRecognizer is protected and not private.
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Re: Custom ID auto generation pattern.

Post by xsaero00 »

How do I reset OptionsStorage? I don't need a programmatic way. Just tell me where can I find the settings file so I can remove it.
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Re: Custom ID auto generation pattern.

Post by xsaero00 »

I found it. Options > Reset Global Options.
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Re: Custom ID auto generation pattern.

Post by xsaero00 »

GenerateIDElementsInfo on constructor

Code: Select all


 public GenerateIDElementsInfo(AuthorAccess authorAccess, GenerateIDElementsInfo defaultOptions) {
//Read the Auto ID Elements Info from options.
this(isAutoGenerateIDs(authorAccess, defaultOptions),
getIDGenerationPattern(authorAccess),
getIDGenerationElements(authorAccess, defaultOptions));
}
does not respect the default IDGenerationPattern provided in defaultOptions. Why? This makes this class impossible to override. Worse yet, this class is included in oxygen.jar so even if I change the code in GenerateIDElementsInfo.java it gets ignored.

I don't know what to do. :?
Radu
Posts: 9055
Joined: Fri Jul 09, 2004 5:18 pm

Re: Custom ID auto generation pattern.

Post by Radu »

Hi Mike,

First about the OptionsStorage:
Using this API you save your preferences in the Oxygen XML preferences files usually located in the folder:
%APPDATA%\com.oxygenxml (for Oxygen for XML Editor)
or:
%APPDATA%\com.oxygenxml.author (for Oxygen XML Author)

About the method I suggested you to overwrite, I enclosed the signature between bold tags and the forum truncated the signature (I fixed it now), it is the same signature you discovered.

The GenerateIDElementsInfo has two constructors, one of them takes the patterns as parameters:

Code: Select all

public GenerateIDElementsInfo(boolean autoGenerateIds, String idGenerationPattern, String[] elementsWithIDGeneration)
The other constructor receives as a parameter the default GenerateIDElementsInfo value as sent for example by the

Code: Select all

Docbook4UniqueAttributesRecognizer.GENERATE_ID_DEFAULTS
About modifying classes from the ro.sync.ecss.extensions.commons package:

Indeed they are also present in the oxygen.jar so any modifications that you make directly to them will be ignored.

but:

You can rename the package ro.sync.ecss.extensions.commons in your Java sources to something else. In this way your customization will use the modified package and the class loader will not prefer the oxygen.jar

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Re: Custom ID auto generation pattern.

Post by xsaero00 »

Thank you for comprehensive answer. I'll look into renaming the package in my sources. I was really hopping to avoid such implementation though. So far I was able to implement everything I need just by extending Docbook5UniqueAttributesRecognizer and GenerateIDElementsInfo. And if it was not for the weird behavior in GenerateIDElementsInfo constructor everything would be fine. :( Is there really a reason why "generation ID pattern" provided by "defaultOptions" argument is ignored in constructor and static value is used? Code like following would work much better and still be perfectly compatible with all other existing code.

Code: Select all



public GenerateIDElementsInfo(AuthorAccess authorAccess, GenerateIDElementsInfo defaultOptions) {
//Read the Auto ID Elements Info from options.
this(isAutoGenerateIDs(authorAccess, defaultOptions),
getIDGenerationPattern(authorAccess, defaultOptions),
getIDGenerationElements(authorAccess, defaultOptions));
}

private static String getIDGenerationPattern(AuthorAccess authorAccess,GenerateIDElementsInfo defaultOptions) {
return authorAccess.getOptionsStorage().getOption(
GENERATE_ID_PATTERN_KEY, defaultOptions.getIdGenerationPattern());
}
Also with current implementation, there is a false sense that all ID generation defaults are defined in Docbook4UniqueAttributesRecognizer.GENERATE_ID_DEFAULTS. Only the "auto-generate" flag and list of elements are respected. The default ID generation pattern is ignored, it just happens to work because it is pulled from the same place of GenerateIDElementsInfo class that constructor uses.

What if someone was to ask you how they can override just the default ID generation pattern? Would you have them copy the sources, rename the packages and re implement bunch of classes? It seems like too much work for such simple task.

Anyways, it seems like a bug. Please tell me what you think of this and whether you are planning on fixing it. I think for now I can work around it by overriding default on every installation, but if you are not planning on fixing this I will start including your code and renaming packages.
Radu
Posts: 9055
Joined: Fri Jul 09, 2004 5:18 pm

Re: Custom ID auto generation pattern.

Post by Radu »

Hi Mike,

I also think this is a bug, the pattern should be taken from the default options object, we'll correct this in Oxygen 13.
You can also probably make it work using some Java reflection to change the private pattern field after you have delegated to the constructor but it's more of a hack really. I'll also add some public setter methods in the class for easier modifying the fields from user code.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
xsaero00
Posts: 58
Joined: Sat Aug 01, 2009 12:57 am

Re: Custom ID auto generation pattern.

Post by xsaero00 »

Since you are looking as this, can you provide a way to override the tooltip in SAIDElementsCustomizerDialog. Currently it just gets set to GenerateIDElementsInfo.PATTERN_TOOLTIP (line 227 in SAIDElementsCustomizerDialog.java)

Code: Select all


//Tooltip for the pattern field    idGenerationPatternField.setToolTipText(GenerateIDElementsInfo.PATTERN_TOOLTIP);
Currently to change it I have to override the whole chain of classes, so I just don't bother, but it would be nice to have a mechanism to do so. A possible way to do it is to move tooltip initialization into showDialog() method and use the available autoIDElementsInfo object.

Code: Select all


  public GenerateIDElementsInfo showDialog(GenerateIDElementsInfo autoIDElementsInfo) {    idGenerationPatternField.setToolTipText(autoIDElementsInfo.PATTERN_TOOLTIP);
.....
Radu
Posts: 9055
Joined: Fri Jul 09, 2004 5:18 pm

Re: Custom ID auto generation pattern.

Post by Radu »

Hi Mike,

I'll see what I can do. I'll probably leave the field public and static with the same name (for backward compatibility) and create a public method which returns it to be used in the dialogs. In this way the method will be overwritten for customizations.

In the meantime, if you still do not want to take the entire commons package over to your implementation (by changing its name) you can use Java reflection to change it's value. But you have to do this before the first show of the dialog (when the AuthorExtensionStateListener is activated for example):

Code: Select all

    try {
Field field = GenerateIDElementsInfo.class.getField("PATTERN_TOOLTIP");
field.setAccessible(true);
field.set(null, "YOUR CUSTOM VALUE HERE");
} catch (Exception e1) {
e1.printStackTrace();
}
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Post Reply