Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Sapphire » Different editors for same file-extensions
Different editors for same file-extensions [message #945222] Mon, 15 October 2012 05:51 Go to next message
Hazem ELRAFFIEE is currently offline Hazem ELRAFFIEE
Messages: 56
Registered: September 2012
Member
Hey all Smile

If I have an XML type called "msxml" and all files following this schema are named "anything.msxml", I'll register its editor like this:
<extension point="org.eclipse.ui.editors">
    <editor
        class="com.hazem.msxmleditor.ui.MSXMLEditor"
        default="true"
        extensions="msxml"
        id="com.hazem.msxmleditor.ui.MSXMLEditor"
        name="MS Editor"/>
</extension>


The problem is that a schema is usually changing by time. That's why a field in an "msxml" file is always reserved for its schema version.

I already created two editors for two versions of the "msxml". What I'm trying to do is to create a generic editor for both versions. The editor should first check that field, in order to determine which editor it should launch, then it launches the correct editor.

Is that possible?
Re: Different editors for same file-extensions [message #945864 is a reply to message #945222] Mon, 15 October 2012 14:29 Go to previous messageGo to next message
Konstantin Komissarchik is currently offline Konstantin Komissarchik
Messages: 923
Registered: July 2009
Senior Member
I can think of several ways to do this:

1. Define different content types for different versions. See "org.eclipse.core.contenttype.contentTypes" extension point. You'd implement a content describer that will be invoked to figure out the file type. You then associate a different editor with each of the content types.

2. Another alternative is to add version detection and selection of the appropriate model+sdef in your subclass of SapphireEditor.

3. A newest alternative that is available in 0.6 release development stream is @Since annotation and other related facilities. This feature set makes it easier to write a single model and sdef for all versions of the file schema. The version can even be changed while the editor is open and the editor will re-arrange itself. There is a small example of this in the purchase order sample. Try changing version to "1.0", "1.5" and "2.0". You will see various properties and sections appear/disappear.

- Konstantin
Re: Different editors for same file-extensions [message #946354 is a reply to message #945864] Tue, 16 October 2012 02:24 Go to previous messageGo to next message
Hazem ELRAFFIEE is currently offline Hazem ELRAFFIEE
Messages: 56
Registered: September 2012
Member
I'm sorry but could you please illustrate solution number 2 ?

If we assume that an attribute in the root tag is named "version" and its value is the schema version:

<msxml version="1.3">
    ...
</msxml>


Could you provide a small example?

Thanks again Smile
Re: Different editors for same file-extensions [message #947905 is a reply to message #946354] Wed, 17 October 2012 11:05 Go to previous messageGo to next message
Konstantin Komissarchik is currently offline Konstantin Komissarchik
Messages: 923
Registered: July 2009
Senior Member
As it happens, a bit ago, Greg Amerson shared some code that does something very similar to what you are trying to do:

https://github.com/liferay/liferay-ide/blob/master/eclipse/portal/plugins/com.liferay.ide.eclipse.hook.ui/src/com/liferay/ide/eclipse/hook/ui/editor/HookXmlEditor.java#L135

Assuming that your editor derives from SapphireEditorForXml, you will want to override createModel() and createFormPages() methods in order to insert your logic that dynamically determines the model type and sdef.

- Konstantin
Re: Different editors for same file-extensions [message #972141 is a reply to message #945222] Mon, 05 November 2012 06:42 Go to previous message
Hazem ELRAFFIEE is currently offline Hazem ELRAFFIEE
Messages: 56
Registered: September 2012
Member
I implemented solution number 1 Smile Actually a friend of mine did it for me Very Happy I would like to share what I reached:

Class XMLRootVersionHandler
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XMLRootVersionHandler extends DefaultHandler {

	String localQualifiedTagName = null;
	String localAttributeName = null;
	String localVersion = null;
	
	boolean nextIsVersion = false;
	
	public void startElement(String uri, String localName, String qname, Attributes attr) throws SAXException {
		if(qname != null && qname.equals(localQualifiedTagName))
		{
			if(localAttributeName==null){
				nextIsVersion = true;
			}else{
				localVersion = attr.getValue(localAttributeName);
				throw new XMLRootVersionTerminatorException();
			}
		}
	}
	public void characters(char[] characters, int start, int length) throws SAXException  {
		if(nextIsVersion){
			localVersion = new String(characters, start, length);
			throw new XMLRootVersionTerminatorException();
		}
	}
	
	public String getVersion(){
		return localVersion;		
	}

	public void setStringsToSearch(String qualifiedTagName, String attributeName){
		localQualifiedTagName = qualifiedTagName;
		localAttributeName = attributeName;
	}
}


Class XMLRootVersionDescriber

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Hashtable;
import org.eclipse.core.internal.content.ContentMessages;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.XMLContentDescriber;
import org.eclipse.osgi.util.NLS;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

@SuppressWarnings({"rawtypes", "unchecked" })
public class XMLRootVersionDescriber extends XMLContentDescriber implements IExecutableExtension {

	Hashtable<String, String> describerParameters = null;	

	static final String qualifiedTagNameParameter = "qualifiedTagName";
	static final String versionParameter = "version";
	static final String attributeNameParameter = "attributeName";
			
	/* (Intentionally not included in javadoc)
	 * @see IContentDescriber#describe(InputStream, IContentDescription)
	 */
	public int describe(InputStream contents, IContentDescription description) throws IOException {

		// super.describe will have consumed some chars, need to rewind		
		contents.reset();
		// Check to see if we matched our criteria.		
		int checkCriteria = checkCriteria(new InputSource(contents));
		System.out.println("v2 Return (1) : " + checkCriteria);
		return checkCriteria;
	}

	/* (Intentionally not included in javadoc)
	 * @see IContentDescriber#describe(Reader, IContentDescription)
	 */
	public int describe(Reader contents, IContentDescription description) throws IOException {
		int checkCriteria = checkCriteria(new InputSource(contents));
		System.out.println("v2 Return (2) : " + checkCriteria);
		return checkCriteria;
	}
		
	private int checkCriteria(InputSource contents) throws IOException {
        XMLRootVersionHandler handler = new XMLRootVersionHandler();
        
		try {
			
	        XMLReader saxReader = XMLReaderFactory.createXMLReader();
	        handler.setStringsToSearch(
	        		describerParameters.get(qualifiedTagNameParameter),
	        		describerParameters.get(attributeNameParameter)
	        		);
			saxReader.setContentHandler(handler);
			saxReader.parse(contents);
			
		}catch (XMLRootVersionTerminatorException e){
			//ok
			String version = (String) handler.getVersion();
			if (version != null && version.equals(describerParameters.get(versionParameter))){
				return VALID;
			}
		}catch (SAXException e) {
			// we may be handed any kind of contents... it is normal we fail to parse
			return INVALID;
		}catch (Exception e) {
			// we may be handed any kind of contents... it is normal we fail to parse
			return INVALID;
		}
		return INVALID;
	}
	
	/* (Intentionally not included in javadoc)
	 * @see IExecutableExtension#setInitializationData
	 */
	public void setInitializationData(final IConfigurationElement config, final String propertyName, final Object data) throws CoreException {
		
		if (data instanceof Hashtable) {
			if(((Hashtable) data).get(qualifiedTagNameParameter) != null && ((Hashtable) data).get(versionParameter) != null ){
				describerParameters = (Hashtable) data;
			}
		}

		if (describerParameters == null) {
			String message = NLS.bind(ContentMessages.content_badInitializationData, XMLRootVersionDescriber.class.getName());
			throw new CoreException(new Status(IStatus.ERROR, ContentMessages.OWNER_NAME, 0, message, null));
		}
	}
}


Class XMLRootVersionTerminatorException

import org.xml.sax.SAXException;

public class XMLRootVersionTerminatorException extends SAXException {

	private static final long serialVersionUID = 4280571238180794197L;

}


"plugin.xml" file should have the following:

<plugin>
  <extension point="org.eclipse.ui.editors">
    <editor
          class="path.to.editor.ui.MSXMLEditor"
          default="true"
          id="path.to.editor.ui.MSXMLEditor"
          name="MSXML Editor">
       <contentTypeBinding
             contentTypeId="path.to.editor.content-type">
       </contentTypeBinding>
    </editor>
  </extension>
  <extension
        point="org.eclipse.core.contenttype.contentTypes">
     <content-type
           base-type="org.eclipse.core.runtime.xml"
           file-extensions="msxml"
           id="path.to.editor.content-type"
           name="MSXML File"
           priority="normal">
       <describer class="path.to.editor.XMLRootVersionDescriber">
        <parameter
              name="qualifiedTagName"
              value="msxml">
        </parameter>
        <parameter
              name="attributeName"
              value="version">
        </parameter>
        <parameter
              name="version"
              value="1.3">
        </parameter>
       </describer>
     </content-type>
  </extension>
</plugin>


Describer parameters are:


  1. qualifiedTagName: Name of the Tag to search for the version inside it. If second parameter "attributeName" is not specified, qualified tag contents will be considered as the version.
  2. attributeName: If version is specified inside an attribute in the qualified tag, specify this attribute name here.
  3. version: The version of your xml that this editor is supposed to handle

[Updated on: Mon, 05 November 2012 07:29]

Report message to a moderator

Previous Topic:Simple custom constraint on a property editor
Next Topic:Announcing Sapphire 0.6 Release
Goto Forum:
  


Current Time: Fri Apr 18 22:02:31 EDT 2014

Powered by FUDForum. Page generated in 0.05215 seconds