Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Getting the Qualified Name and Global Name Collision
Getting the Qualified Name and Global Name Collision [message #659995] Wed, 16 March 2011 14:12 Go to next message
Rafael Angarita is currently offline Rafael AngaritaFriend
Messages: 94
Registered: November 2010
Member
Hello everybody,

I'm still having trouble with the issue I mentioned here: http:// www.eclipse.org/forums/index.php?t=msg&th=205127&sta rt=0&S=191eb7b65a1bd2dd68b2c6d3b9bf6a4e. I have made a little example grammar to post here, and see If you guys can give me an advise on how to do these things right in Xtext.

This is the problem I have: I need to cross-references diferent objects from one of my grammars, so I am referencing EObjects:

EObject:
	name=ID objectag=[ecore::EObject]
;



This is the grammar for one of the objects I need to reference:

AFile:
	name=ID
;


Here is the grammar of another object which can reference objects of the type AFile:

Model:
	name=ID reference=Reference
;

Reference:
	afile=[aRef::AFile]
;


Inside this last grammas, I have to referece objects of type "reference" already declared in Model, so I had to compute de qualified name for "reference":

public class ArefQNP extends DefaultDeclarativeQualifiedNameProvider {
	@Override
	public String getQualifiedName(EObject obj) {
		if(obj instanceof Reference) {
			Reference col = ((Reference) obj);
			CompositeNode cNode = NodeUtil.getNode(col);
			EList<AbstractNode> anList = cNode.getChildren();
			if (anList.size() > 1){
				AbstractNode aNode = anList.get(1);
				LeafNode lNode = (LeafNode) aNode;
				return lNode.getText();
			}
		}
		return super.getQualifiedName(obj);
	}
}


Now, If I have an AFile reference in a model (therefore its qualified name was computed) and can't reference the same AFile in the EObject object because I get: "Couldn't resolve reference to EObject 'MyAFile'."

I would appreciate if someone knows the right way or the best practice to solve this.

Thank you very much for all your help.




Re: Getting the Qualified Name and Global Name Collision [message #660004 is a reply to message #659995] Wed, 16 March 2011 14:21 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Hi,

don't you have two objects with the same name then? which one should be chosen then?

~Christian


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Getting the Qualified Name and Global Name Collision [message #660013 is a reply to message #660004] Wed, 16 March 2011 14:41 Go to previous messageGo to next message
Rafael Angarita is currently offline Rafael AngaritaFriend
Messages: 94
Registered: November 2010
Member
Hi Christian,

I know that if I have two objects with the same name there would be no way to know which one should be chosen. The things is tha conceptually (in my project) I have only one object: the one defined in Afile.

If I reference this AFile in a Model object, it shouldn't be another object with the same name, but I know that when I compute its qualified name to make it referencebale within the same Model object, the referenced object is exported to the global namespace with the same name. I would like to make this qualified name computation only visible to Model objects.

I know I could set a diferente QN for the referenced objects, for example: "nameofAFileObject.model" instead of just nameofAFileObject, but it wouldn't be what we want for our DSL.


How would you guys do it?

Thank you for your advises,




Re: Getting the Qualified Name and Global Name Collision [message #660015 is a reply to message #660013] Wed, 16 March 2011 14:49 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Hi,

i still have problems you get your problem Wink

you want to reference AFiles and therefor you introduced the Reference construct to kind of "import" it and make it available locally? I'd solve such a problem using scoping only.

~Christian


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Getting the Qualified Name and Global Name Collision [message #660025 is a reply to message #660015] Wed, 16 March 2011 15:08 Go to previous messageGo to next message
Rafael Angarita is currently offline Rafael AngaritaFriend
Messages: 94
Registered: November 2010
Member
That's it. Cool

I'm trying writing a scope provider por my EObject grammar:

public IScope scope_Register_objectag(Register i, EReference r) {
		IScope result = delegateGetScope(i, r);
		Iterable<IEObjectDescription> objects = Iterables.filter(result.getAllContents(), new Predicate<IEObjectDescription>() {
			@Override
			public boolean apply(IEObjectDescription input) {
				return input.getEObjectURI().fileExtension().equals("afile");
			}
		});
		return new SimpleScope(objects);
	}



, but I get the error: "getAllContents shouldn't be called on a global scope during linking". I don't kow If I should just ignore this error (I don't want it to break something in the future Sad ). I tried doing the filtering as the the arithmetics example but it doesn't work for this.


Thank you Christian.
Re: Getting the Qualified Name and Global Name Collision [message #660030 is a reply to message #660025] Wed, 16 March 2011 15:19 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Hi,

yes you have toi do the stuff lazy as it is done with the class org.eclipse.xtext.scoping.impl.FilteringScope.

(build a wrapping scope arround the delegate scope and do the filterinmg/transformation on the fly)

It seems that you want to get all AFiles, so what about

public IScope scope_EObject_objecttag(EObject o, EReference ref) {
		return new FilteringScope(delegateGetScope(o, ref), MyDslPackage.Literals.AFILE);
	}


this simply gets you all AFile objects into the scope.

maybe a look at the scope implementation of org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalSc opeProvider might be a look worth. here some kind of aliasing is done too.

~Christian



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Wed, 16 March 2011 15:31]

Report message to a moderator

Re: Getting the Qualified Name and Global Name Collision [message #660522 is a reply to message #659995] Fri, 18 March 2011 20:26 Go to previous messageGo to next message
Rafael Angarita is currently offline Rafael AngaritaFriend
Messages: 94
Registered: November 2010
Member
HI, Christian. Thank you very much for your help. I have tried several things, but none of them have worked for me. I rewrote my sample grammar to make it less confusing:

First I have a Table which can contain Columns and Indexes:

Table:
	'Name:' name=ID
	'Columns:' '{' columns+=Column (',' columns+=Column)* '}'
	'Indexes:' '{' indexes+=Index+ '}'
;

Column:
	attribute=[ColumnRef::Column]
;


Index: {Index}
	'Columns:'  '{' indexcolumns+=IndexColumn (',' indexcolumns+=IndexColumn)* '}'
;

IndexColumn:
	indexColumn=[Column]
;


To compute the QN of Table.Column and make it referencable within its table I wrote the next methods:

@Override
	public String getQualifiedName(EObject obj) {
		System.out.println("getQualifiedName");
		if(obj instanceof Column) {
			System.out.println("Column");
			Column col = ((Column) obj);
			CompositeNode cNode = NodeUtil.getNode(col);
			EList<AbstractNode> anList = cNode.getChildren();
			if (anList.size() > 1){
				AbstractNode aNode = anList.get(1);
				LeafNode lNode = (LeafNode) aNode;
				System.out.println(lNode.getText());
				return lNode.getText();
			}
		}
		return super.getQualifiedName(obj);
	}


       @Inject
	IQualifiedNameProvider nameProvider;

	public IScope scope_IndexColumn_indexColumn(Index i, EReference r) {
		EList<Column> list = ((Table) i.eContainer())
				.getColumns();
		return Scopes.scopeFor(list, nameProvider, IScope.NULLSCOPE);
	}




I define a Column in another file:

Column:
	name=ID
;


Now, I have another object wich can reference objects of different types, so I use a reference to a EObject:

Procedure:
	'object: ' eo=[ecore::EObject]
;


Suppose I want only Columns to be referenced in my Procedure. I have tried the next to do the filtering:


1. Using the filtering from the arithmetics example:

@Override
	public IScope getScope(EObject context, EReference reference) {
		IScope scope = super.getScope(context, reference);
		return new FilteringScope(scope,
				new Predicate<IEObjectDescription>() {
				@Override
					public boolean apply(IEObjectDescription input) {
						//System.out.println(input.getQualifiedName());
						return input!=null && input.getEObjectURI()!=null &&  input.getEObjectURI().fileExtension()!=null &&
						(input.getEObjectURI().fileExtension().equals("column"));
					};
				});
	}


The content proposed for the EObjects of my Procedure is filtered well, only Columns are showed. However, If I choose a Column that was used as a Table index, I still get the error: "Couldn't resolve reference to EObject".

2. I tried:


@Override
	public IScope getScope(EObject context, EReference reference) {
		return new org.eclipse.xtext.scoping.impl.FilteringScope(delegateGetScope(context, reference), ColumnPackage.Literals.COLUMN);

	}


But it did nothing at all.

3. I wrote the method:

public IScope scope_Procedure_eo(Procedure i, EReference r) {
		//System.out.println("ss");
		IScope result = delegateGetScope(i, r);
		Iterable<IEObjectDescription> objects = Iterables.filter(result.getAllContents(), new Predicate<IEObjectDescription>() {
			@Override
			public boolean apply(IEObjectDescription input) {
				return input.getEObjectURI().fileExtension().equals("column");
			}
		});
		return new SimpleScope(objects);
		//return new SimpleScope(objects);
	}


It actually do the filtering very well, but I get the error: "getAllContents schouldn't be called on a global scope during linking"

I guess there is no way to make the Columns of a table only visible to the current Table when computing the QN. The QN is always exported to the global scope.

Sorry for the long, long post, but I am really stuck here.

Thank you very much for your help.










Re: Getting the Qualified Name and Global Name Collision [message #660527 is a reply to message #660522] Fri, 18 March 2011 21:24 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Hi,

The Following works nice for me.

(1) First remove the NameProvider Thing. In my case
public class TablesQNP extends DefaultDeclarativeQualifiedNameProvider {

}


(2) Adapt the Scoping for the IndexColumns
	public IScope scope_IndexColumn_indexColumn(Index i, EReference r) {
		EList<Column> list = ((Table) i.eContainer())
				.getColumns();
		Function<Column, String> nameProvider = new Function<Column, String>() {
			@Override
			public String apply(Column from) {
				CompositeNode cNode = NodeUtil.getNode(from);
				EList<AbstractNode> anList = cNode.getChildren();
				if (anList.size() > 1){
					AbstractNode aNode = anList.get(1);
					LeafNode lNode = (LeafNode) aNode;
					return lNode.getText();
				}
				return null;
			}
		};
		return Scopes.scopeFor(list,nameProvider, IScope.NULLSCOPE);
	}

Using just a local name provider prevents fron pluplicate things are thrown to the index.

(3) Adapt Scoping for the Procedure thing
package org.xtext.example.ref.scoping;

import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
import org.eclipse.xtext.scoping.impl.FilteringScope;
import org.xtext.example.columns.columns.ColumnsPackage;
import org.xtext.example.ref.ref.Procedure;

/**
 * This class contains custom scoping description.
 * 
 * see : http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping
 * on how and when to use it 
 *
 */
public class RefScopeProvider extends AbstractDeclarativeScopeProvider {
	
	public IScope scope_Procedure_eo(Procedure i, EReference r) {
		return new FilteringScope(delegateGetScope(i, r), ColumnsPackage.Literals.COLUMN);
	}

}


This works nicly for me.

~Christian


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Getting the Qualified Name and Global Name Collision [message #660534 is a reply to message #660527] Fri, 18 March 2011 22:31 Go to previous message
Rafael Angarita is currently offline Rafael AngaritaFriend
Messages: 94
Registered: November 2010
Member
Thank you Christian! It worked perfectly! I still have so much to learn.

Cheers!
Previous Topic:[xtext] is lexical analysis over syntactic analysis in xtext?
Next Topic:Terminal extension + problem with enum
Goto Forum:
  


Current Time: Thu Mar 28 17:53:19 GMT 2024

Powered by FUDForum. Page generated in 0.03648 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top