Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Customize Scoping for inheritance
Customize Scoping for inheritance [message #1839773] Sun, 28 March 2021 11:53 Go to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi all,

I have the following grammar in Xtext where Countries extend Countries. By that I want to support inheritance. The following is my grammar and afterwards I will be showing some examples of what I want to achieve.

grammar org.xtext.example.forest.Forest with org.eclipse.xtext.common.Terminals

generate forest "http://www.xtext.org/example/forest/Forest"

Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])?
	"{"
	forests=Forest
	"}"
	;
Forest:
	"{" 
	name=ID 
	("tree" trees+=Tree ("," trees+=Tree)*)*
	("house" houses+=House ("," houses+=House)*)*
	("remove" remove=[Tree|QualifiedName])?
	("remove" remove=[House|QualifiedName])?
	;
Tree:
	name=ID
;
House:
	name=ID
;
QualifiedName:
 ID ('.' ID)*
 ;


The example is as follows:
file1.dsl 

country C1 {
   forest {
      tree T1, T2;
     house H1, H2;
     }
}


file2.dsl

country C2 extends C1 {
   forest  {
      remove T1; 
     remove H2;
     }
}


I want to customize the Scope Provider so that when I say country C2 extends C1, I will get suggestions only from C1 (because if I were to work with the Default Scope Provider and I would have a third file with Country C3, I would get suggestions from there too which I do not want).

I also tried the approach of using imports, but that doesn't work well for me either. I have been trying to find examples on how to customize this scope provider to achieve what I want but I have not been able to.

Your help is highly appreciated.

Thanks!
Re: Customize Scoping for inheritance [message #1839774 is a reply to message #1839773] Sun, 28 March 2021 12:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
what is unclear to me in all your questions. what is the problem with simply implement scoping

- from the context object search the Country (EcoreUtil.getContainerOfType might help)
- from the country recursively collect and decollect all Tree and Houses
- put the result of Trees and Houses to a Scope (Scope.scopesFor util will help here)

as you dont post any snippet of scope provider it is hard to find out where your problem is.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839779 is a reply to message #1839774] Sun, 28 March 2021 14:42 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

Thank you for your reply!

Up until now, from an example I found online I have only been able to implement this.
@Override
public IScope getScope(EObject context, EReference reference) {
    if (context instanceof Country
            && reference == ForestPackage.Literals.COUNTRY__SUPER_COUNTRY) {
        EObject rootCountry = EcoreUtil2.getRootContainer(context);
        List<Element> candidates = EcoreUtil2.getAllContentsOfType(rootCountry, Country.class);
        return Scopes.scopeFor(candidates);
    }
    return super.getScope(context, reference);
}


But I am not really sure how accurate this is and how to implement the rest (collect and decollect trees and houses).

Haven't been able to find an example on how to really code this.

Thank you!
Re: Customize Scoping for inheritance [message #1839782 is a reply to message #1839779] Sun, 28 March 2021 17:16 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
still dont see the problem

reference == ForestPackage.Literals.FOREST__REMOVE

country.getForests().getTrees()
country.getForests().getHouses()
same for superCountry if not null.



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839783 is a reply to message #1839782] Sun, 28 March 2021 18:31 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
When I try to write this example:

Country C2 extend C1 


I get: Could not resolve reference to Country C1.

Or is it that I do not need this implementation of the scope provider at all?
public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    if (context instanceof Country
	            && reference == ForestPackage.Literals.COUNTRY__SUPERCOUNTRY) {
	        EObject rootCountry = EcoreUtil2.getRootContainer(context);
	        List<Country> candidates = EcoreUtil2.getAllContentsOfType(rootCountry, Country.class);
	        return Scopes.scopeFor(candidates);
	    }
	    return super.getScope(context, reference);
	}
}


Thanks for your help!
Re: Customize Scoping for inheritance [message #1839784 is a reply to message #1839783] Sun, 28 March 2021 19:11 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
do you want to scope supercountry?
Why don't you use default scoping for that
You code allows countries from the same file only
If that what you intend?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839792 is a reply to message #1839784] Mon, 29 March 2021 08:27 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
For the Country, the perfect option would be to be able to choose from all projects, but if that is not possible at least choose between the countries that are defined in files that are part of the same project, not just in one file. So the base Country and inherited Country are part of two different files.

As I said I do not have much experience with this so it is a bit hard for me to implement it but i tried the following, and I still get errors:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    if (context instanceof Country
	            && reference == ForestPackage.Literals.FOREST__REMOVE) {
	        EObject rootCountry = EcoreUtil2.getRootContainer(context);
	        Country.getForests().getTrees();
	        Country.getForests().getHouses();
	        List<Country> candidates = EcoreUtil2.getAllContentsOfType(rootCountry, Country.class);
	        return Scopes.scopeFor(candidates);
	    }
	    return super.getScope(context, reference);
	}
}



Cannot make a static reference to the non-static method getForests() from the type
Country
- Cannot make a static reference to the non-static method getForests() from the type
Country
Re: Customize Scoping for inheritance [message #1839793 is a reply to message #1839792] Mon, 29 March 2021 08:47 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
why Country.getForests().getTrees();

and not

Country coutry = (Country) context;
country.getForests().getTrees();


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839795 is a reply to message #1839793] Mon, 29 March 2021 09:32 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
I tried this out:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    if (context instanceof Country
	            && reference == ForestPackage.Literals.FOREST__REMOVE) {
	        EObject rootCountry = EcoreUtil2.getRootContainer(context);
	        Country country=(Country) context;
	        country.getForests().getTrees();
	        country.getForests().getHouses();
	        List<Country> candidates = EcoreUtil2.getAllContentsOfType(rootCountry, Country.class);
	        return Scopes.scopeFor(candidates);
	    }
	    return super.getScope(context, reference);
	}
}



But when I use the keyword remove, I still get suggestions from all the Countries specified in xtext files in the same project, while I want to get suggestions only from the Country from which I am inheriting.
Re: Customize Scoping for inheritance [message #1839801 is a reply to message #1839795] Mon, 29 March 2021 10:07 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
still dont understand
are you talking about countries or about trees and houses.
why do you show scoping snippet for remove/houses/trees
but complain about countries.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839810 is a reply to message #1839801] Mon, 29 March 2021 10:55 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Okay, so I might have misdirected you, but this is what I want to do with an example.Note that these are three different files in one project.

file1.dsl 

country C1 { forest F1 
	tree T1, T2
	house H1, H2
	}


file2.dsl 

country C2 { forest F2
	tree T3, T4
	house H3, H4
	}


file3.dsl 

country C3 inherits C2 { forest F3
	tree T5, T6
	house H5, H6
       remove T3 //here I should only get suggestions for T5, T6 which are part of C3, and T3,T4 which are inherited from C2. However, with the scope provider snippet that I have, I still get suggestions even for T1, and T2 which are part of C1 and I dont want that. 
	}


I understand that the code snippet I already have might be wrong, but I would very much appreciate your help as I really need it for a project.

Many thanks!
Re: Customize Scoping for inheritance [message #1839816 is a reply to message #1839810] Mon, 29 March 2021 12:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
yes but where is your proper impl of the scope provider?

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    if (context instanceof Country
	            && reference == ForestPackage.Literals.FOREST__REMOVE) {
	        EObject rootCountry = EcoreUtil2.getRootContainer(context);
	        Country country=(Country) context;
	        country.getForests().getTrees();
	        country.getForests().getHouses();
	        List<Country> candidates = EcoreUtil2.getAllContentsOfType(rootCountry, Country.class);
	        return Scopes.scopeFor(candidates);
	    }
	    return super.getScope(context, reference);
	}
}


is not the impl you use for sure.
you should collect the valid trees and houses there


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839819 is a reply to message #1839816] Mon, 29 March 2021 12:46 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
this one works fine for me

public class MyDslScopeProvider extends AbstractMyDslScopeProvider {
	
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    if (reference == MyDslPackage.Literals.FOREST__REMOVE) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> treesAndHouses = new ArrayList<>();
	        while (rootCountry != null) {
	        	treesAndHouses.addAll(rootCountry.getForests().getTrees());
	        	treesAndHouses.addAll(rootCountry.getForests().getHouses());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(treesAndHouses);
	        return Scopes.scopeFor(treesAndHouses);
	    }
	    return super.getScope(context, reference);
	}


}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839822 is a reply to message #1839819] Mon, 29 March 2021 14:14 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
That works wonders. Thank you very much.

I will now try to adapt this to my grammar as it is much more complicated, but I just needed a starting point on how this works.

Thanks again!
Re: Customize Scoping for inheritance [message #1839861 is a reply to message #1839819] Tue, 30 March 2021 13:52 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

I am currently working on customizing the scope provider for my grammar, and it works for most of it. However, I have issues in a specific case.

So being that Xtexts' default scope provider allows you to reference elements from all the files that are part of the same project by using the qualified name, I want to restrict that. I removed the qualified name but with the following grammar and the following scope provider I am not able to refer to trees specified in country which I am extending.

This is the grammar:
Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])?
	forests=Forest
	;
Forest:
	"{" 
	"forest" name=ID 
	("tree" trees+=Tree ("," trees+=Tree)*)*
	("workingArea" position+=Position)*
	("house" houses+=House ("," houses+=House)*)*
	("remove" remove=[Tree|QualifiedName])?
	;
Tree:
	name=ID
;
Position:
	name=ID "from" from=[Tree] "to" from=[Tree] 
;

House:
	name=ID
;
QualifiedName:
 ID ('.' ID)*
 ;


These are the examples:
file1.forest

country C1 { forest F1 
	tree T1, T2


file2.forest 

country C2 extends C1 { 
	forest F2 
	tree T7 
	workingArea area from T7 to T7 //here I also want to be able to refer to T1, and T2, but I can't.


This is a snippet of my scope provider. The second part else if, is what I am trying to implement to make this possible, but I can't seem to get it right.

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    if (reference == ForestPackage.Literals.FOREST__REMOVE) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> treesAndHouses = new ArrayList<>();
	        while (rootCountry != null) {
	        	treesAndHouses.addAll(rootCountry.getForests().getTrees());
	        	treesAndHouses.addAll(rootCountry.getForests().getHouses());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(treesAndHouses);
	        return Scopes.scopeFor(treesAndHouses);
	    }
	    else if (reference == ForestPackage.Literals.FOREST__POSITION) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> position = new ArrayList<>();
	        while (rootCountry != null) {
	        	position.addAll(rootCountry.getForests().getPosition());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(position);
	        return Scopes.scopeFor(position);
	    }
	    return super.getScope(context, reference);
	}
}



Thank you!
Re: Customize Scoping for inheritance [message #1839862 is a reply to message #1839861] Tue, 30 March 2021 13:59 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Position:
name=ID "from" from=[Tree] "to" from=[Tree]
;

looks bogus. should be

Position:
name=ID "from" from=[Tree] "to" to=[Tree]
;

+ scoping for Position__from and Position__to (and not FOREST__POSITION)




Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839947 is a reply to message #1839862] Thu, 01 April 2021 17:24 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

I am trying to access a specific element from my grammar and I have been trying for a while but no luck.

This is the grammar:

Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])?
	forests=Forest
	;
Forest:
	"{" 
	"forest" name=ID "{"
	("tree" trees+=Tree ("," trees+=Tree)*)*
	("house" houses+=House ("," houses+=House)*)*
	"subforest" subforest+=Subforest
	"}";
Tree:
	name=ID
;
Position:
	name=ID "from" from=[Enter] "to" to=[Exit] 
;

House:
	name=ID
;
Subforest:
	name=ID
	"enter" enter+=Enter
	"exit" exit+=Exit 
	("tree" trees+=Tree ("," trees+=Tree)*)*
	("workingArea" position+=Position)*
	("house" houses+=House ("," houses+=House)*)*
;
Enter:
	name=ID
;
Exit:
	name=ID
;

QualifiedName:
 ID ('.' ID)*
 ;



And this is my scope provider:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.POSITION__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> position = new ArrayList<>();
	        while (rootCountry != null) {
	        	position.addAll(rootCountry.getForests(). getSubforest());

	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(position);
	        return Scopes.scopeFor(position);
	    }
	    return super.getScope(context, reference);
	}
}



I want to be able to access Enter and Exit so the position will be from enter to exit. Both enter and exit are contained by a subforest, but when I write this line in my scope provider:

position.addAll(rootCountry.getForests(). getSubforest());


I cannot go further than getSubforest() , while I have the idea that in order to access enter and exit I should be able to write

position.addAll(rootCountry.getForests(). getSubforest().getEnter());
position.addAll(rootCountry.getForests(). getSubforest().getExit);

Re: Customize Scoping for inheritance [message #1839954 is a reply to message #1839947] Fri, 02 April 2021 04:40 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
getSubforest Returns a list so you may loop over it

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839964 is a reply to message #1839954] Fri, 02 April 2021 10:35 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Would it be something like this?

 while (rootCountry != null) {
	        	return position.addAll(rootCountry.getForests().getSubforest());
	            
Re: Customize Scoping for inheritance [message #1839968 is a reply to message #1839964] Fri, 02 April 2021 12:01 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
?????

for (Subforest sf :rootCountry.getForests().getSubforest()){
//ask sf for enters and exits
}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839969 is a reply to message #1839968] Fri, 02 April 2021 12:21 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
With the following implementation of the scope provider I cannot seem to get a suggestion for FROM:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.POSITION__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> position = new ArrayList<>();
	        while (rootCountry != null) {
	        	for (Subforest sf :rootCountry.getForests().getSubforest()){
	        		sf.getEnter();
	        		}
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(position);
	        return Scopes.scopeFor(position);
	    }
	    return super.getScope(context, reference);
	}
}

Re: Customize Scoping for inheritance [message #1839970 is a reply to message #1839969] Fri, 02 April 2021 12:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
You nowhere add the forms to the scope list

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839972 is a reply to message #1839970] Fri, 02 April 2021 12:40 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
I tried to add this line to the grammar

 position.add(sf);


But I get sf cannot be resolved to a variable

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.POSITION__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> position = new ArrayList<>();
	        while (rootCountry != null) {
	        	for (Subforest sf :rootCountry.getForests().getSubforest()){
	        		sf.getEnter();
	        		}
	        	position.add(sf);
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(position);
	        return Scopes.scopeFor(position);
	    }
	    return super.getScope(context, reference);
	}
}

Re: Customize Scoping for inheritance [message #1839974 is a reply to message #1839972] Fri, 02 April 2021 12:43 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
sf.getEnter()

Maybe this should be

position.add(sf.getEnter())


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

[Updated on: Fri, 02 April 2021 12:45]

Report message to a moderator

Re: Customize Scoping for inheritance [message #1839976 is a reply to message #1839974] Fri, 02 April 2021 14:44 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
It works for this case, but for a more complex case like the following it doesnt:

This is the grammar:

Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])?
	forests=Forest
	;
Forest:
	"{" 
	"forest" name=ID "{"
	("park" parks+=Park ("," parks+=Park)*)*
	"workingarea"  workingarea=WorkingArea
	"}";
	
Park:
     name=ID ("{"
	"enter" enter+=Enter
	"exit" exit+=Exit
	("park" parks+=Park ("," parks+=Park)*)*
	"workingarea"  workingarea=WorkingArea
	"}")*
;
WorkingArea:
	name=ID "from" from=[ParkEnter] "to" to=[ParkExit] 
;

Enter:
	Name=ID
;
Exit:
	Name=ID
;
ParkEnter:
	Park | Enter
;
ParkExit:
	Park | Exit
;

QualifiedName:
 ID ('.' ID)*
 ;



And this is the scope provider:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        	for (Park park :rootCountry.getForests().getParks()){
	        		workingarea.addAll(park.getEnter());
	        		}
	        	workingarea.addAll(rootCountry.getForests().getParks());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(workingarea);
	        return Scopes.scopeFor(workingarea);
	    }
	   else if (reference == ForestPackage.Literals.WORKING_AREA__TO) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingareato = new ArrayList<>();
	        while (rootCountry != null) {
	        	for (Park park :rootCountry.getForests().getParks()){
	        		workingareato.addAll(park.getExit());
	        		}
	        	workingareato.addAll(rootCountry.getForests().getParks());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(workingareato);
	        return Scopes.scopeFor(workingareato);
	    }
	    return super.getScope(context, reference);
	}
}


However, if I try to write this example I cannot. I have put some comments in the grammar to show what is wrong.

country C1 {
	forest F1 {
		park P1 {
			enter Enter1 
			exit Exit1
			park P2
			workingarea W1 from P1 to P1  \\here I want to be able to say from  and to P1, Enter1,Exit1, P2 , but I am only allowed to say P1
		}
        park P3 {
        	enter Enter2 
        	exit Exit2
        	park P4
        	workingarea W2 from P1 to P3 \\here I want to be able to say from  and to P1, Enter1,Exit1, P2 ,P3,Enter2,Exit2 and P4 but I am only allowed to say P1 and P3.
        	}
        }
}


Many thanks!
Re: Customize Scoping for inheritance [message #1839977 is a reply to message #1839976] Fri, 02 April 2021 15:21 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
i recommend you to debug your code.
make sure you collect the objects you want.
workingarea W1 from P1 to P1 \\here I want to be able to say from and to P1, Enter1,Exit1, P2 , but I am only allowed to say P1
if you want Exit1 you should collect it.

besides that your example grammar has warnings and the example model does not parse.
so i cannot look into it


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839980 is a reply to message #1839977] Fri, 02 April 2021 16:15 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
p.s.

in your sample you have

Enter:
Name=ID
;

and not

Enter:
name=ID
;

did you adapt IQualifiedNameProvider then?
https://dietrich-it.de/xtext/2011/07/16/iqualifiednameproviders-in-xtext-2.0/
and pass it to the scopeFor method?

of course renaming Name to name would help
also and be much much simpler


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

[Updated on: Fri, 02 April 2021 16:26]

Report message to a moderator

Re: Customize Scoping for inheritance [message #1839984 is a reply to message #1839980] Fri, 02 April 2021 20:50 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Ok, the grammar should work fine now. I changed Enter: name=ID but I cannot change Exit too because I get :

Quote:

There cannot be two features named "name".


grammar org.xtext.example.forest.Forest with org.eclipse.xtext.common.Terminals

generate forest "http://www.xtext.org/example/forest/Forest"

Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])? "{"
	forests=Forest
	"}"
	;
Forest:	
	"forest" name=ID "{"
	("park" parks+=Park ("," parks+=Park)*)*
	("workingarea"  workingarea=WorkingArea)*
	"}";
	
Park:
     name=ID ("{"
	"enter" enter+=Enter
	"exit" exit+=Exit
	("park" parks+=Park ("," parks+=Park)*)*
	("workingarea"  workingarea=WorkingArea)*
	"}")*
;
WorkingArea:
	name=ID "from" from=[ParkEnter] "to" to=[ParkExit] 
;

Enter:
	name=ID
;
Exit:
	Name=ID
;
ParkEnter:
	Park | Enter
;
ParkExit:
	Park | Exit
;

QualifiedName:
 ID ('.' ID)*
 ;

This is the example and there are comments there to explain what I need:

country C1 {
	forest F1 {
		park P1 {
			enter EN1
			exit EX1
			park P2 {
				enter EN2
				exit EX2
				park P3 
				park P4 {
					enter EN3 
					exit EX3
					park P5
					workingarea W4 from EN1 to P2 //need to have from: P5, P4.EN3 to: P5,P4.EX3 because P4 only contains P4.EN3,P4.EX3 and P5
				}
			 workingarea W2 from EN1 to P2 //need to have from: P2.EN2, P3, P4, P4.EN3  to: P2.EX2, P3, P4,P4.EX3 because P2 contains P2.EN2, P2.EX2, P3, P4, P4.EN3 and P4.EX3. Contrary to others, here we have two parks contained in one park therefore we also allow P3 and P4, not only P4.EN3 and P4.EX3
			}
         workingarea W1 from EN1 to P2 //need to have from: P1.EN1  to:  P1.EX1		
		}
		park P6 {
			enter EN4 
			exit EX4
			}
		workingarea WF from EN4 to P6 // here I currently have from: EN1, EN4,P1,P2,P6 . I should not have P2 , I should only have P1, P6, P1.EN1,P6.EN4. To should be: P1.EX1, P6.EX4, P1,P6
	}
}



So to summarize each working area that belongs to a park, should allow cross referencing enter and exit of that same park, sub parks of that park and the corresponding enter and exit. However, the current scope provider only allows to cross reference park P1, park P6 and their corresponding enter and exit (EN1,EX1,EN4,EX4) but not their sub parks and corresponding enter and exit (it allows the same thing throughout the entire grammar).

For the forest, I should not have P2, because it is a subpark of P1. I should only have P1, P6 and their corresponding enter and exit.
Hope this isn't too complex.

This is the scope provider.

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        	for (Park park :rootCountry.getForests().getParks()){
	        		workingarea.addAll(park.getParks());
	        		workingarea.addAll(park.getEnter());
	        		}
	        	workingarea.addAll(rootCountry.getForests().getParks());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(workingarea);
	        return Scopes.scopeFor(workingarea);
	    }
	   else if (reference == ForestPackage.Literals.WORKING_AREA__TO) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingareato = new ArrayList<>();
	        while (rootCountry != null) {
	        	for (Park park :rootCountry.getForests().getParks()){
	        		workingareato.addAll(park.getParks());
	        		workingareato.addAll(park.getExit());
	        		}
	        	workingareato.addAll(rootCountry.getForests().getParks());
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(workingareato);
	        return Scopes.scopeFor(workingareato);
	    }
	    return super.getScope(context, reference);
	}
}


I think the current scope provide only collects the first (P1, P6) and second (P2) level of parks and their respective enter and exit points, but it does not go deeper than that, while in my case I guess I have to check until there are no more parks.
Many thanks!

[Updated on: Fri, 02 April 2021 22:50]

Report message to a moderator

Re: Customize Scoping for inheritance [message #1839988 is a reply to message #1839984] Sat, 03 April 2021 05:31 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
You can introduce a

Named : ParkEnter | ParkExit ;

To be able to have name=ID again

Maybe EcoreUtil2.getAllContentsOfType might help you to collect
All stuff under the root
If you cannot do it with recursive traversal


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

[Updated on: Sat, 03 April 2021 05:33]

Report message to a moderator

Re: Customize Scoping for inheritance [message #1839994 is a reply to message #1839988] Sat, 03 April 2021 09:01 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
What approach would you suggest?

I feel like it is better to do recursive traversal but when I tried to add a while loop

while(park!=null)


That didn't really work
Re: Customize Scoping for inheritance [message #1839998 is a reply to message #1839994] Sat, 03 April 2021 14:00 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
you can also create a recursive method to collect or whatever you feel good with when using java

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1839999 is a reply to message #1839998] Sat, 03 April 2021 14:46 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
I tried the following, so that when a park is not null (it has enter, exit or other subparks), it should add them to the working area, and then assign these parks to park and check again if the park is null or it has subparks, but now I don't get any suggestions at all.

 if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        for (Park park :rootCountry.getForests().getParks()) 
	        	{
	        	while (park !=null) {
	        		workingarea.addAll(park.getParks()); 
	        		workingarea.addAll(park.getEnter());
	        		park = (Park) park.getParks();
	        	}	
	        }
	        	rootCountry = rootCountry.getSupercountry();
	        
	       System.out.println(workingarea);
	        return Scopes.scopeFor(workingarea);
	    }
	  }
Re: Customize Scoping for inheritance [message #1840053 is a reply to message #1839998] Tue, 06 April 2021 08:02 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

Any idea on why this is not working or how it can be resolved as I am currently stuck at this point in the project.

Many thanks!
Re: Customize Scoping for inheritance [message #1840054 is a reply to message #1840053] Tue, 06 April 2021 08:08 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
i have lost the overview what your actual problem is.
unfortunately i dont have the time to program the tree traveral code for you.

did you check the EcoreUtil2.getAllContentsOfType?
did you solve the Name vs name problem.
did you use a debugger to find out which parts of the tree you miss?


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

[Updated on: Tue, 06 April 2021 08:09]

Report message to a moderator

Re: Customize Scoping for inheritance [message #1840066 is a reply to message #1840054] Tue, 06 April 2021 10:08 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
I was actually just trying the recursive method as I thought it would work out better and not really sure what is wrong with what I already implemented.

Yeah the name issue is ok, now I am just trying to implement the scope provider for from and I changed the Enter Name to name.

I tried to come up with the following scope provider where I try to implement EcoreUtil2.getAllContentsOfType but I still do not get any suggestions for that.

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	       
	        for (Park park :rootCountry.getForests().getParks()) 
	        	{
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(park,null));
	        	}	
	        }
	        	rootCountry = rootCountry.getSupercountry();
	        
	       System.out.println(workingarea);
	        return Scopes.scopeFor(workingarea);
	    }
	  
	
	    return super.getScope(context, reference);
	}
}


Re: Customize Scoping for inheritance [message #1840068 is a reply to message #1840066] Tue, 06 April 2021 10:47 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
:(

EcoreUtil2.getAllContentsOfType(object, TypeYouWtoCollect)

e.g.

EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class), no for loop needed


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840070 is a reply to message #1840068] Tue, 06 April 2021 11:24 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

Thank you for your help!

Even though this approach is a bit different from what I wanted (I wanted to be able to cross reference only the subelements of a park and not everything), it is still fine.

However, now I am trying to have the following

workingarea W2 from P2.E2
while the grammar now only allows me to have
working area W2 from E2

Isn't the DefaultDeclarativeQualifiedNameProvider supposed to provide P2.E2? I have not made any changes to it.

This is the grammar:

Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])? "{"
	forests=Forest
	"}"
	;
Forest:	
	"forest" name=ID "{"
	("park" parks+=Park ("," parks+=Park)*)*
	("workingarea"  workingarea=WorkingArea)*
	"}";
	
Park:
     name=ID ("{"
	"enter" enter+=Enter
	("park" parks+=Park ("," parks+=Park)*)*
	("workingarea"  workingarea=WorkingArea)*
	"}")*
;
WorkingArea:
	name=ID "from" from=[ParkEnter|QualifiedName] 
;

Enter:
	name=ID
;

ParkEnter:
	Park | Enter
;

QualifiedName:
 ID ('.' ID)*
 ;



And this is the scope provider:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class));   	
	        
	        	rootCountry = rootCountry.getSupercountry();
	        }
	       System.out.println(workingarea);
	        return Scopes.scopeFor(workingarea);
	    }
	  
	
	    return super.getScope(context, reference);
	}
}



Many thanks!
Re: Customize Scoping for inheritance [message #1840071 is a reply to message #1840070] Tue, 06 April 2021 11:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
yes this is that is passed to the overloads of scopeFor (there is one that accepts a fuction that calc a qualifiedname

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840076 is a reply to message #1840071] Tue, 06 April 2021 12:11 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Sorry, didn't quite understand that.

Do I need to change the scope provider now?
Re: Customize Scoping for inheritance [message #1840087 is a reply to message #1840076] Tue, 06 April 2021 13:54 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
yes you have to call Scopes.scopeFor(listOfObjects,Function<YoutObject, QualifiedName>,IScope.NULLSCOPE)

make sure you create the QalifiedNames with proper segments (no . in segments) with QUalifiedName.create
or use IQualifiedNameConverter (injected to ScopeProvider)


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840093 is a reply to message #1840087] Tue, 06 April 2021 16:16 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

So one possibility is to do the following?

return Scopes.scopeFor(workingarea, QualifiedName.create(segments), IScope.NULLSCOPE);


But instead of segments, what should I put to get a qualified name for the enter?

Something like : P1. enter1 (don't really want to start from the country or forest).

Re: Customize Scoping for inheritance [message #1840095 is a reply to message #1840093] Tue, 06 April 2021 16:42 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
no you need to pass a function or closure.
you can use eContainer() on an eObject to get the parent, then downcast it.

e.g.

List<ParkEnter> workingarea = new ArrayList<ParkEnter>();
return Scopes.scopeFor(workingarea, (ParkEnter e) -> {
Park p = (Park) e.eContainer();
return QualifiedName.create(p.getName(), e.getName());
}, IScope.NULLSCOPE);


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840102 is a reply to message #1840095] Tue, 06 April 2021 20:40 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
I tried out the following scope provider where instead of :
List<EObject> workingarea = new ArrayList<>();


I put

List<ParkEnter> workingarea = new ArrayList<ParkEnter>();


Because I couldn't say :

List<ParkEnter> workingarea = new ArrayList<ParkEnter>();
return Scopes.scopeFor(workingarea, (ParkEnter e) -> {
Park p = (Park) e.eContainer();
return QualifiedName.create(p.getName(), e.getName());
}, IScope.NULLSCOPE);


Being that I already had declared a working area.

This is the scope provider that I am using:
public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);
	        List<ParkEnter> workingarea = new ArrayList<ParkEnter>();
	       // List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class));   	
	        
	        	rootCountry = rootCountry.getSupercountry();
	        	
	        }
	       System.out.println(workingarea);

        return Scopes.scopeFor(workingarea, (ParkEnter e) -> {
        Park p = (Park) e.eContainer();
        return QualifiedName.create(p.getName(), e.getName());
         }, IScope.NULLSCOPE);
	    }
	  
	    return super.getScope(context, reference);
	}
}



But I do not get any suggestions when I try to write the grammar
Re: Customize Scoping for inheritance [message #1840116 is a reply to message #1840102] Wed, 07 April 2021 03:58 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Please please debug your code and the scope provider
And the proposal provider

also check the console for errors.
this would have helped you to find the problem an solve it

:(

			Function<ParkEnter, QualifiedName> nameComputation = (ParkEnter e) -> {
				EObject eContainer = e.eContainer();
				if (eContainer instanceof Park) {
					Park p = (Park) eContainer;
					return QualifiedName.create(p.getName(), e.getName());
				}
				return QualifiedName.create(e.getName());
			};
			return Scopes.scopeFor(workingarea, nameComputation, IScope.NULLSCOPE);


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

[Updated on: Wed, 07 April 2021 04:10]

Report message to a moderator

Re: Customize Scoping for inheritance [message #1840129 is a reply to message #1840116] Wed, 07 April 2021 08:29 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

Sorry for all the hustle.

I tried your approach, but first on this line:
Function<ParkEnter, QualifiedName> nameComputation = (ParkEnter e) -> {


I got an error saying:

Quote:

Multiple markers at this line
- The target type of this expression must be a functional
interface
- Function cannot be resolved to a type


So I imported com.google.common.base.Function

However afterwards I got an error on this line:

return Scopes.scopeFor(workingarea, nameComputation, IScope.NULLSCOPE);


saying:

Quote:

Multiple markers at this line
- The method scopeFor(Iterable<? extends T>, Function<T,QualifiedName>, IScope) in the type Scopes is not applicable for the arguments (List<EObject>,
Function<ParkEnter,QualifiedName>, IScope)
- The method scopeFor(Iterable<? extends T>, Function<T,QualifiedName>, IScope) in the type Scopes is not applicable for the arguments (List<EObject>,
Function<ParkEnter,QualifiedName>, IScope)


This is the full scope provider:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);

	       List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class));   	
	        
	        	rootCountry = rootCountry.getSupercountry();
	        	
	        }
	       System.out.println(workingarea);

			Function<ParkEnter, QualifiedName> nameComputation = (ParkEnter e) -> {
				EObject eContainer = e.eContainer();
				if (eContainer instanceof Park) {
					Park p = (Park) eContainer;
					return QualifiedName.create(p.getName(), e.getName());
				}
				return QualifiedName.create(e.getName());
			};
			return Scopes.scopeFor(workingarea, nameComputation, IScope.NULLSCOPE);

	    }
	  
	    return super.getScope(context, reference);
	}
}



Many thanks once again!
Re: Customize Scoping for inheritance [message #1840130 is a reply to message #1840129] Wed, 07 April 2021 08:31 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
i recommend you to do some java training first

Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
// do instanceof shit here
};


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840139 is a reply to message #1840130] Wed, 07 April 2021 09:58 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

Yes you are right that is why it is so hard for me to customize this scope provider. However I still get issues, maybe it is something related to the EObject e, because in row:

return QualifiedName.create(p.getName(),e.getName());


And in row
return QualifiedName.create(e.getName());


I get

Quote:

- The method getName() is undefined for the type EObject


Which I would not get when there was ParkEnter instead of EObject.

This is the full scope provider

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);

	       List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class));   	
	        
	        	rootCountry = rootCountry.getSupercountry();
	        	
	        }
	       System.out.println(workingarea);
	     
	       Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
				EObject eContainer = e.eContainer();
				if (eContainer instanceof Park) {
					Park p = (Park) eContainer;
					return QualifiedName.create(p.getName(),e.getName());
				}
				return QualifiedName.create(e.getName());
			};
			
	       return Scopes.scopeFor(workingarea, nameComputation, IScope.NULLSCOPE);
	    }
	  
	    return super.getScope(context, reference);
	}
}



Many thanks!
Re: Customize Scoping for inheritance [message #1840141 is a reply to message #1840139] Wed, 07 April 2021 10:14 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
as i said: use instanceof, downcast .....

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840147 is a reply to message #1840141] Wed, 07 April 2021 11:48 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Ok so if I am not mistaken (take a look at the comments in the code)

EObject eContainer = e.eContainer();
				if (eContainer instanceof Park) { // here I use instanceof
					Park p = (Park) eContainer;	//here I do downcasting


But is there something else I should do to get to e.getname().

Sorry I bothered you with this, is just that this is the last remaining issue in my project that I need to solve
Re: Customize Scoping for inheritance [message #1840149 is a reply to message #1840147] Wed, 07 April 2021 11:52 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
(EObject e) -> {
=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>
well you need to make instanceof on e as well



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840152 is a reply to message #1840149] Wed, 07 April 2021 14:17 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

I tried the following function

    Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
				EObject eContainer = e.eContainer();
				if (eContainer instanceof Park) {
					Park p = (Park) eContainer;	
					if (e instanceof Enter) {
						Enter en = (Enter) eContainer;
					}
					return QualifiedName.create(p.getName(), en.getname());
				}
				return QualifiedName.create(en.getName());
			};


But I still cannot get en.getname()

I get errors saying :

Quote:

Multiple markers at this line
- The method getname() is undefined for the type
EObject
- en cannot be resolved


Many thanks once again!
Re: Customize Scoping for inheritance [message #1840153 is a reply to message #1840152] Wed, 07 April 2021 15:38 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
question: how firm are you with java programming?

//pseudo code
Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
if (e instanceof ParkEnter) {
... container logic
} else if (e instanceof OtherStuffYOurPutTOTHATLIST) {
.......
} elseif (e instanceof ThridStuff) {
.....
}
else {
throw new IllegalStateException("did not expect an " e.GetClass().getName() +"here");
}



EObject eContainer = e.eContainer();
if (eContainer instanceof Park) {
Park p = (Park) eContainer;
if (e instanceof Enter) {
Enter en = (Enter) eContainer;
}
return QualifiedName.create(p.getName(), en.getname());
}
return QualifiedName.create(en.getName());
};


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840159 is a reply to message #1840153] Wed, 07 April 2021 19:58 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

I tried a few things with the grammar :

First I tried the following function:

 Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	    	   if (e instanceof Park)
	    	   {
	    		   Park p = (Park) e;
	    	      return QualifiedName.create(p.getName(), ((Park) e).getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter) e).getName());	    
	       };

But here I get Park.Park and not Park.Enter () because of this line:
p.getName(), ((Park) e).getName()

Afterwards I tried the following function:

Quote:

Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
if (e instanceof ParkEnter)
{
ParkEnter p = (ParkEnter) e;
return QualifiedName.create(p.getName(), ((ParkEnter) e).getName());
}
return QualifiedName.create(((ParkEnter) e).getName());
};


Here I get Park.Park and Enter.Enter being that ParkEnter: Park | Enter, but still I don't get Park.Enter

Now I am trying the following:

Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	    	   if (e instanceof Enter)
	    	   {		  
	    		  Enter en = (Enter) e;
	    	      return QualifiedName.create(Park.getName(), en.getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter) e).getName());	    
	       };


because I want to have Park.getName() , Enter.getName, but I don't really know how to access Enter, and the Park to which that Enter belongs to.
In this scope provider I get an error because

Quote:

Cannot make a static reference to the non-static method getName() from the type
ParkEnter


I am including the grammar once again:

Country:
	"country" name=ID ("extends" supercountry=[Country|QualifiedName])? "{"
	forests=Forest
	"}"
	;
Forest:	
	"forest" name=ID "{"
	("park" parks+=Park ("," parks+=Park)*)*
	("workingarea"  workingarea=WorkingArea)*
	"}";
	
Park:
     name=ID ("{"
	"enter" enter+=Enter
	("park" parks+=Park ("," parks+=Park)*)*
	("workingarea"  workingarea=WorkingArea)*
	"}")*
;
WorkingArea:
	name=ID "from" from=[ParkEnter|QualifiedName] 
;

Enter:
	name=ID
;

ParkEnter:
	Park | Enter
;

QualifiedName:
 ID ('.' ID)*
 ;



And the scope provider:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);

	       List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class));   	
	        
	        	rootCountry = rootCountry.getSupercountry();
	        	
	        }
	       System.out.println(workingarea);
	       
	       Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	    	   if (e instanceof Enter)
	    	   {		  
	    		  Enter en = (Enter) e;
	    	      return QualifiedName.create(Park.getName(), en.getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter) e).getName());	    
	       };
	       /*
	       Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	    	   if (e instanceof ParkEnter)
	    	   {
	    		   ParkEnter p = (ParkEnter) e;
	    	      return QualifiedName.create(p.getName(), ((ParkEnter) e).getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter) e).getName());	    
	       };
	       */
	      /* 
	       Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	    	   if (e instanceof Park)
	    	   {
	    		   Park p = (Park) e;
	    	      return QualifiedName.create(p.getName(), ((Park) e).getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter) e).getName());	    
	       };
		*/
	       return Scopes.scopeFor(workingarea, nameComputation, IScope.NULLSCOPE);
	    }
	  
	    return super.getScope(context, reference); 
	}
}
Re: Customize Scoping for inheritance [message #1840170 is a reply to message #1840159] Thu, 08 April 2021 04:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Park is a Class and not a variable.

as you have Seen you can use eContainer to access parents
And you can ask the parent for its parent and you get the grandparent .
Where is this code gone? Why have you removed it

You can Also use EcoreUtil2.getContainerOfType(object, TypeOfAncestorYouSearch.class)


Please please consult somebody with basic java knowledge.
I will stop answering here as long as the problem boils down
To lacking java knowledge


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840179 is a reply to message #1840170] Thu, 08 April 2021 08:09 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Ok thank you, I will try to sort something out.

One final questions as I got confused trying out different things.
When I write this part:

Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	    	   EObject eContainer = e.eContainer();
	    	   if (eContainer instanceof Park)


The eContainer should be an instanceof Park,Enter or ParkEnter.

Many thanks for your help!
Re: Customize Scoping for inheritance [message #1840180 is a reply to message #1840179] Thu, 08 April 2021 08:29 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
then use else if and another else if

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840182 is a reply to message #1840180] Thu, 08 April 2021 08:45 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Sorry for the misunderstanding, that was actually in the form of a question.

If I want to have Park.Enter, I should start with

if (eContainer instanceof Park) ? or
if (eContainer instanceof Enter)? or
if (eContainer instanceof ParkEnter)?

or should I have all three of them using if elseif elseif.

So my biggest issue is starting from instanceof Park I should be able to access Enter or vice versa?
Re: Customize Scoping for inheritance [message #1840183 is a reply to message #1840182] Thu, 08 April 2021 08:57 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
i dont understand
why eContainer and not
e

if (e instanceof ParkEnter) {
...
} else if (e instanceof OtherStuffYouPutToTheList) {
....
}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840184 is a reply to message #1840183] Thu, 08 April 2021 09:06 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
From your earlier message :

Quote:

Park is a Class and not a variable.

as you have Seen you can use eContainer to access parents
And you can ask the parent for its parent and you get the grandparent .
Where is this code gone? Why have you removed it


I thought I should add it.
Re: Customize Scoping for inheritance [message #1840185 is a reply to message #1840184] Thu, 08 April 2021 09:53 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
I was able to resolve it with the following approach:

 Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	   
	    	   if (e instanceof Enter)
	    	   {		  
	    		 Enter en = (Enter) e;
	             Park p = EcoreUtil2.getContainerOfType(en, Park.class);
	             
	    	      return QualifiedName.create(p.getName(), en.getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter)e).getName());    
	       };


Thank you so much for all your help.
Re: Customize Scoping for inheritance [message #1840192 is a reply to message #1840183] Thu, 08 April 2021 12:09 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
Hi Christian,

I was able to solve the issue that I had before, but now I was wondering about something else. With the following scope provider:

public class ForestScopeProvider extends AbstractForestScopeProvider {
	@Override
	public IScope getScope(EObject context, EReference reference) {
	    
	   if (reference == ForestPackage.Literals.WORKING_AREA__FROM) {
	        Country rootCountry = (Country) EcoreUtil2.getRootContainer(context);

	       List<EObject> workingarea = new ArrayList<>();
	        while (rootCountry != null) {
	        			workingarea.addAll(EcoreUtil2.getAllContentsOfType(rootCountry, ParkEnter.class));   		        
	        	rootCountry = rootCountry.getSupercountry();	        	
	        }
	       System.out.println(workingarea);
	        
	       Function<EObject, QualifiedName> nameComputation = (EObject e) -> {
	   
	    	   if (e instanceof Enter)
	    	   {		  
	    		 Enter en = (Enter) e;
	             Park p = EcoreUtil2.getContainerOfType(en, Park.class);
	             
	    	      return QualifiedName.create(p.getName(), en.getName());
	    	   }
	    	   return QualifiedName.create(((ParkEnter)e).getName());    
	       };
	       return Scopes.scopeFor(workingarea, nameComputation, IScope.NULLSCOPE);
	    }	  
	    return super.getScope(context, reference); 
	}
}


I should use the qualified name even when I cross reference elements in the same hierarchical level. For example in the following grammar(please read the comment).

country C1 {
	forest F1 {
		park P1 {
			enter EN1
		
			park P2 {
				enter EN2
			
				park P3 
				park P4 {
					enter EN3 
				
					park P5
					workingarea W4 from P4.EN3. // here it should be EN3 because both EN3 and W4 are Part of P4. If I were to have EN2, that I should write it as P2.EN2, as it is not part of P4. 
				}
			 workingarea W2 from P2
			}
         workingarea W1 from P6.EN4
		}
		park P6 {
			enter EN4 
			}
		workingarea WF from P6.EN4
  } 
} 


Is there a way around this?

Many thanks!
Re: Customize Scoping for inheritance [message #1840196 is a reply to message #1840192] Thu, 08 April 2021 12:58 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
simply implement this is in your if else.
have a look at the context object that is passed to the scope method.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Customize Scoping for inheritance [message #1840198 is a reply to message #1840196] Thu, 08 April 2021 13:31 Go to previous message
John Henbergs is currently offline John HenbergsFriend
Messages: 239
Registered: October 2020
Senior Member
No Message Body

[Updated on: Thu, 08 April 2021 14:27]

Report message to a moderator

Previous Topic:missing RULE_BEGIN if using whitespace-aware
Next Topic:Qualified Name according to the hierarchical level
Goto Forum:
  


Current Time: Thu Mar 28 10:29:46 GMT 2024

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

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

Back to the top