Home » Modeling » TMF (Xtext) » using the index to check for duplicates
using the index to check for duplicates [message #1018774] |
Thu, 14 March 2013 12:55 |
|
Hi
looking at Christian's answer in the thread
http://www.eclipse.org/forums/index.php/mv/msg/261440/754503/#msg_754503
I was trying to check for duplicates across multiple files using the code
public class MyDslJavaValidator extends AbstractMyDslJavaValidator {
@Inject
ResourceDescriptionsProvider resourceDescriptionsProvider;
@Inject
IContainer.Manager containerManager;
@Check(CheckType.NORMAL)
public void checkGreetingsDuplicate(Greeting greeting) {
Set<QualifiedName> names = new HashSet<QualifiedName>();
IResourceDescriptions resourceDescriptions =
resourceDescriptionsProvider.getResourceDescriptions(greeting.eResource());
IResourceDescription resourceDescription =
resourceDescriptions.getResourceDescription(greeting.eResource().getURI());
for (IContainer c :
containerManager.getVisibleContainers(resourceDescription,
resourceDescriptions)) {
for (IEObjectDescription od :
c.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
if (!names.add(od.getQualifiedName())) {
error("duplicate greeting", MyDslPackage.Literals.GREETING__NAME);
}
}
}
}
}
However, at least in a plugin project, the same name (of the same
element) appears in different containers as far as I understand (by
debugging I see StateBasedContainer, EObjectDescriptionImpl,
DescriptionAddingContainer), thus the above strategy raises an error
even for a single element (in this example Greeting), though there are
actually no duplicates.
Thus, in general, one should use a new set in the inner loop (and exit
as soon as there's an error, otherwise, the same error is reported twice):
@Check(CheckType.NORMAL)
public void checkGreetingsDuplicate(Greeting greeting) {
IResourceDescriptions resourceDescriptions =
resourceDescriptionsProvider.getResourceDescriptions(greeting.eResource());
IResourceDescription resourceDescription =
resourceDescriptions.getResourceDescription(greeting.eResource().getURI());
for (IContainer c :
containerManager.getVisibleContainers(resourceDescription,
resourceDescriptions)) {
// each time create a new set
Set<QualifiedName> names = new HashSet<QualifiedName>();
for (IEObjectDescription od :
c.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
if (!names.add(od.getQualifiedName())) {
error("duplicate greeting", MyDslPackage.Literals.GREETING__NAME);
// avoid reporting the same error twice
return;
}
}
}
}
can anyone confirm this please?
thanks
Lorenzo
--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
HOME: http://www.lorenzobettini.it
HOME: http://www.lorenzobettini.it
TDD Book: https://leanpub.com/tdd-buildautomation-ci
Xtext Book: https://www.packtpub.com/application-development/implementing-domain-specific-languages-xtext-and-xtend-second-edition
|
|
|
Re: using the index to check for duplicates [message #1018932 is a reply to message #1018774] |
Thu, 14 March 2013 18:05 |
Sebastian Zarnekow Messages: 3118 Registered: July 2009 |
Senior Member |
|
|
Hi Lorenzo,
first you should check for duplicates in the local resource for
efficiency reasons and more helpful user feedback. If the local resource
is valid, a full check could be performed. There you may want to use the
list of visible containers but filter for descriptions from the very
same resource. This should do the trick.
Best regards,
Sebastian
--
Looking for professional support for Xtext, Xtend or Eclipse Modeling?
Go visit: http://xtext.itemis.com
Am 14.03.13 13:55, schrieb Lorenzo Bettini:
> Hi
>
> looking at Christian's answer in the thread
>
> http://www.eclipse.org/forums/index.php/mv/msg/261440/754503/#msg_754503
>
> I was trying to check for duplicates across multiple files using the code
>
> public class MyDslJavaValidator extends AbstractMyDslJavaValidator {
>
> @Inject
> ResourceDescriptionsProvider resourceDescriptionsProvider;
>
> @Inject
> IContainer.Manager containerManager;
>
> @Check(CheckType.NORMAL)
> public void checkGreetingsDuplicate(Greeting greeting) {
> Set<QualifiedName> names = new HashSet<QualifiedName>();
> IResourceDescriptions resourceDescriptions =
> resourceDescriptionsProvider.getResourceDescriptions(greeting.eResource());
> IResourceDescription resourceDescription =
> resourceDescriptions.getResourceDescription(greeting.eResource().getURI());
> for (IContainer c :
> containerManager.getVisibleContainers(resourceDescription,
> resourceDescriptions)) {
> for (IEObjectDescription od :
> c.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
> if (!names.add(od.getQualifiedName())) {
> error("duplicate greeting", MyDslPackage.Literals.GREETING__NAME);
> }
> }
> }
> }
>
> }
>
> However, at least in a plugin project, the same name (of the same
> element) appears in different containers as far as I understand (by
> debugging I see StateBasedContainer, EObjectDescriptionImpl,
> DescriptionAddingContainer), thus the above strategy raises an error
> even for a single element (in this example Greeting), though there are
> actually no duplicates.
>
> Thus, in general, one should use a new set in the inner loop (and exit
> as soon as there's an error, otherwise, the same error is reported twice):
>
> @Check(CheckType.NORMAL)
> public void checkGreetingsDuplicate(Greeting greeting) {
> IResourceDescriptions resourceDescriptions =
> resourceDescriptionsProvider.getResourceDescriptions(greeting.eResource());
> IResourceDescription resourceDescription =
> resourceDescriptions.getResourceDescription(greeting.eResource().getURI());
> for (IContainer c :
> containerManager.getVisibleContainers(resourceDescription,
> resourceDescriptions)) {
> // each time create a new set
> Set<QualifiedName> names = new HashSet<QualifiedName>();
> for (IEObjectDescription od :
> c.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
> if (!names.add(od.getQualifiedName())) {
> error("duplicate greeting", MyDslPackage.Literals.GREETING__NAME);
> // avoid reporting the same error twice
> return;
> }
> }
> }
> }
>
> can anyone confirm this please?
>
> thanks
> Lorenzo
>
>
|
|
|
Re: using the index to check for duplicates [message #1019261 is a reply to message #1018932] |
Fri, 15 March 2013 10:31 |
|
On 03/14/2013 07:05 PM, Sebastian Zarnekow wrote:
> Hi Lorenzo,
>
> first you should check for duplicates in the local resource for
> efficiency reasons and more helpful user feedback. If the local resource
> is valid, a full check could be performed. There you may want to use the
> list of visible containers but filter for descriptions from the very
> same resource. This should do the trick.
Hi Sebastian
actually in this code I don't want to check for duplicates in the very
resource (I have a validator method specific for that, or I'm simply
relying on NamesAreUniqueValidator): in this method I want to check that
there are no duplicates across different files, thus I want the object
descriptions from different resources (that's also the intention of the
answer found at
http://www.eclipse.org/forums/index.php/mv/msg/261440/754503/#msg_754503 ).
Thus, for instance, I want to avoid situations like (this is a
simplified example, the real context is a language with qualified names,
imports, etc.)
first.mydsl contains
Hello foo! // (1)
second.mydsl contains
Hello foo! // (2)
However, as I said in the original post, I seem to understand that in an
Eclipse instance, if you write your DSL programs in a plugin project,
there are several different containers storing qualified names
StateBasedContainer [ 'foo' referring to (1), 'foo' referring to (2), ... ]
DescriptionAddingContainer [ 'foo' referring to (1), 'foo' referring to
(2), ... ]
thus I should NEVER flatten the containers lists, otherwise I end up with
[ 'foo' referring to (1), 'foo' referring to (2), ... , 'foo' referring
to (1), 'foo' referring to (2), ... ]
right?
in particular this flattening would raise a duplicate error even if
there is no duplicate, e.g., even if there's only one file in my project
with a single Hello foo, the containers would be
StateBasedContainer [ 'foo' ... ]
DescriptionAddingContainer [ 'foo' ... ]
and flattened they would give
[ 'foo' ... , 'foo' ... ]
which would raise a duplicate error, while there's no duplicate.
Thus my original question was: the correct way of checking for duplicate
names in different files, is not the one found at
http://www.eclipse.org/forums/index.php/mv/msg/261440/754503/#msg_754503
which I report partially
Set<QualifiedName> names = new HashSet<QualifiedName>();
....
for (IContainer c :
containerManager.getVisibleContainers(resourceDescription,
resourceDescriptions)) {
for (IEObjectDescription od :
c.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
if (!names.add(od.getQualifiedName())) {
error("duplicate greeting"...
}
}
}
which implicitly flattens all the lists of containers
but
for (IContainer c :
containerManager.getVisibleContainers(resourceDescription,
resourceDescriptions)) {
// each time create a new set
Set<QualifiedName> names = new HashSet<QualifiedName>();
for (IEObjectDescription od :
c.getExportedObjectsByType(MyDslPackage.Literals.GREETING)) {
if (!names.add(od.getQualifiedName())) {
error("duplicate greeting", ...);
// avoid reporting the same error twice
return;
}
}
}
which scans a container's list at time (and exits as soon a duplicate is
found). Is that correct?
I mean, this second solution works, but I wanted to be sure that it is
the right strategy to use the index for looking for duplicates.
By the way, the problems I was telling about are not showing in a junit
scenario, since there's basically only one container. It's only when you
use the DSL editor for a program in an Eclipse plugin project.
thanks
Lorenzo
--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
HOME: http://www.lorenzobettini.it
HOME: http://www.lorenzobettini.it
TDD Book: https://leanpub.com/tdd-buildautomation-ci
Xtext Book: https://www.packtpub.com/application-development/implementing-domain-specific-languages-xtext-and-xtend-second-edition
|
|
| |
Re: using the index to check for duplicates [message #1019317 is a reply to message #1019302] |
Fri, 15 March 2013 12:37 |
|
On 03/15/2013 01:05 PM, Christian Dietrich wrote:
> Lorenzo,
>
> does this work is you really have two containers aka projects?
>
> ~Christian
Christian, I'm not sure what you mean but what happens is that, if I use
my solution
- I correctly get errors if I have elements with the same name
(qualified name) in two different files of the same project
- I don't get errors if these two files are in different projects
- most of all, I don't get false errors (because the same name of the
same element is in several visible containers)
by error I mean "duplicate greeting" error issued by the validator's
check method
or did you mean something else?
Concerning your original code, does it work for you? Because what happens is
- even with a single file I get a false error with a single element
(since it appears in several visible containers)
I can try to put on github an example (as soon as I have time :)
thanks in advance
Lorenzo
--
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
HOME: http://www.lorenzobettini.it
HOME: http://www.lorenzobettini.it
TDD Book: https://leanpub.com/tdd-buildautomation-ci
Xtext Book: https://www.packtpub.com/application-development/implementing-domain-specific-languages-xtext-and-xtend-second-edition
|
|
| | | | | |
Goto Forum:
Current Time: Fri Apr 19 19:50:41 GMT 2024
Powered by FUDForum. Page generated in 0.03319 seconds
|