Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » VIATRA » Matches not send to change listener
Matches not send to change listener [message #1826168] Mon, 20 April 2020 15:10 Go to next message
Hans van der Laan is currently offline Hans van der LaanFriend
Messages: 34
Registered: February 2020
Member
Hey,

I've just finished my proposal, which means I can finally return to experimenting with Viatra! :)

I'm observing some behavior I'm not sure how to explain. It seems as a specific match update listener is blocking something unless I interact with the engine.

Consider the following model:

https://pasteboard.co/J4H8pLH.png

and some basic patterns:

pattern policy(policy: Policy) {
    Policy(policy);
}

pattern roleName(role: Role, name : java String) {
    Role.name(role,name);
}

pattern userShouldHaveARole(user: User) {
    neg User.UR(user, _);
}

pattern accessRelation(user: User, permission: Permission) {
    User.UR(user,role);
    Role.RD(role, demarcation);
   	Demarcation.DP(demarcation, permission);
}


Weirdly after I've added a match update listener for the "accessRelation" query, for all other match update listeners I add afterwards the existing matches are only given to the listeners after I interact with the engine.
For example: When I first add a match change listener for "userShouldHaveARole", then for "accessRelation" and lastly for "roleName", the match listener for "roleName" will only be invoked after I interact with the engine (e.g. calling getAllMatches()/applying a model transformation).

Why is this happening?

Aditionally, in the documentation of "addMatchUpdateListener()", a function "addCallbackAfterUpdates(Runnable)" is mentioned. Where can we find this function? The link is not working and I can not find it the ViatraQueryEngine nor the AdvancedViatraQueryEngine.

Kind regards,

Hans

PS:
A program which shows this behaviour:
package validator;

import java.util.function.Consumer;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine;
import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
import org.eclipse.viatra.query.runtime.emf.EMFScope;
import org.eclipse.viatra.transformation.runtime.emf.modelmanipulation.IModelManipulations;
import org.eclipse.viatra.transformation.runtime.emf.modelmanipulation.SimpleModelManipulations;
import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRule;
import org.eclipse.viatra.transformation.runtime.emf.rules.batch.BatchTransformationRuleFactory;
import org.eclipse.viatra.transformation.runtime.emf.transformation.batch.BatchTransformation;
import org.eclipse.viatra.transformation.runtime.emf.transformation.batch.BatchTransformationStatements;
import org.eclipse.xtext.xbase.lib.Extension;

import com.google.common.base.Objects;

import queries.AccessRelation;
import queries.Policy;
import queries.RoleName;
//import queries.SameRoleName;
import queries.TestQueries;
import queries.UserShouldHaveARole;

public class Validator implements IApplication {

	@Extension
	private BatchTransformation transformation;
	@Extension
	private BatchTransformationStatements statements;
	@Extension
	private BatchTransformationRuleFactory factory = new BatchTransformationRuleFactory();
	@Extension
	private IModelManipulations manipulation;

	@Override
	public Object start(IApplicationContext context) throws Exception {
		
		System.out.println("Validator Called!");
		System.out.print("Initialize model scope and preparing engine... ");
		EMFScope scope = initializeModelScope();
		AdvancedViatraQueryEngine engine = prepareAdvancedQueryEngine(scope);
		System.out.println(" Done!");
		
		Thread.sleep(5000);
		
		System.out.println("\nAdding Change Listeners... ");
		addChangeListeners(engine);
		System.out.println("Done!");
		
		Thread.sleep(5000);
		
		System.out.println("\nSearching for Access Relation Matches... ");
		//printAllAccessRelationMatches(engine);
		System.out.println("Done!");
		
		System.out.println("\nSearching for Users without a role... ");
		printAllUserShouldHaveARoleMatches(engine);
		System.out.println("Done!");
		
		Thread.sleep(5000);
		
		System.out.println("\nCreate and Execute Model Transformation");
		//createTransformation(engine);
		//execute();
		System.out.println("Done!");
		
		return 0; 
	}

	@Override
	public void stop() {
		// Headless applications do not require specific stop steps
	}

	private EMFScope initializeModelScope() {
		ResourceSet rs = new ResourceSetImpl();
		rs.getResource(URI.createPlatformPluginURI("rbacviatratest/trebla.rbac", true), true);

		return new EMFScope(rs);
	}

	private AdvancedViatraQueryEngine prepareAdvancedQueryEngine(EMFScope scope) {
		AdvancedViatraQueryEngine engine = AdvancedViatraQueryEngine.createUnmanagedEngine(scope);

		// Initialize all queries on engine
		TestQueries.instance().prepare(engine);

		return engine;
	}

	private void addChangeListeners(AdvancedViatraQueryEngine engine) {
		// fireNow = true parameter means all current matches are sent to the listener
		
		engine.addMatchUpdateListener(UserShouldHaveARole.Matcher.on(engine), ListenerFactory.getUserShouldHaveARoleUpdateListener(), true);
		engine.addMatchUpdateListener(AccessRelation.Matcher.on(engine), ListenerFactory.getAccessRelationUpdateListener(), true);
		engine.addMatchUpdateListener(RoleName.Matcher.on(engine), ListenerFactory.getRoleNameMatchUpdateListener(), true);
	}
	
	private void printAllAccessRelationMatches(ViatraQueryEngine engine) {
		AccessRelation.Matcher matcher = AccessRelation.Matcher.on(engine);
		for (AccessRelation.Match match : matcher.getAllMatches()) {
			System.out.println("Found Access Relation:" + match.prettyPrint());
		}
	}
	
	private void printAllUserShouldHaveARoleMatches(ViatraQueryEngine engine) {
		UserShouldHaveARole.Matcher matcher = UserShouldHaveARole.Matcher.on(engine);
		for (UserShouldHaveARole.Match match : matcher.getAllMatches()) {
			System.out.println("Found user without role:" + match.prettyPrint());
		}
	}
	
	public void execute() {
		System.out.println("Execute Called!");
		this.statements.<Policy.Match>fireOne(this.getExampleRule());
	}

	private BatchTransformationStatements createTransformation(AdvancedViatraQueryEngine engine) {
		BatchTransformationStatements _xblockexpression = null;
		{
			SimpleModelManipulations _simpleModelManipulations = new SimpleModelManipulations(engine);
			this.manipulation = _simpleModelManipulations;
			this.transformation = BatchTransformation.forEngine(engine).build();
			_xblockexpression = this.statements = this.transformation.getTransformationStatements();
		}
		return _xblockexpression;
	}

	  private BatchTransformationRule<Policy.Match, Policy.Matcher> getExampleRule() {
		    final Consumer<Policy.Match> _function = (Policy.Match it) -> {
		    	it.getPolicy().getRoles().get(0).setName("R2");
		    };
		    final BatchTransformationRule<Policy.Match, Policy.Matcher> exampleRule = this.factory.<Policy.Match, Policy.Matcher>createRule(Policy.instance()).action(_function).build();
		    return exampleRule;
	  }

	public void dispose() {
		boolean _notEquals = (!Objects.equal(this.transformation, null));
		if (_notEquals) {
			this.transformation.getRuleEngine().dispose();
		}
		this.transformation = null;
		return;
	}

}


With the listeners defined as:
	public static IMatchUpdateListener<RoleName.Match> getRoleNameMatchUpdateListener() {
		return new IMatchUpdateListener<RoleName.Match>() {
			@Override
			public void notifyAppearance(RoleName.Match match) {
				System.out.printf("[ADD RoleName Match] %s %n", match.prettyPrint());
			}
	
			@Override
			public void notifyDisappearance(RoleName.Match match) {
				System.out.printf("[REM RoleName Match] %s %n", match.prettyPrint());
	
			}
		};
	}
	
	public static IMatchUpdateListener<UserShouldHaveARole.Match> getUserShouldHaveARoleUpdateListener() {
		return new IMatchUpdateListener<UserShouldHaveARole.Match>() {
			@Override
			public void notifyAppearance(UserShouldHaveARole.Match match) {
				System.out.printf("[ADD UserShouldHaveARole Match] %s %n", match.prettyPrint());
			}
	
			@Override
			public void notifyDisappearance(UserShouldHaveARole.Match match) {
				System.out.printf("[REM UserShouldHaveARole Match] %s %n", match.prettyPrint());
	
			}
		};
	}
	public static IMatchUpdateListener<AccessRelation.Match> getAccessRelationUpdateListener() {
		return new IMatchUpdateListener<AccessRelation.Match>() {
			@Override
			public void notifyAppearance(AccessRelation.Match match) {
				System.out.printf("[ADD AccessRelation Match] %s %n", match.prettyPrint());
			}
	
			@Override
			public void notifyDisappearance(AccessRelation.Match match) {
				System.out.printf("[REM AccessRelation Match] %s %n", match.prettyPrint());
	
			}
		};
	}
	


Debug output:

Validator Called!
Initialize model scope and preparing engine...  Done!

Adding Change Listeners... 
[ADD UserShouldHaveARole Match] "user"=Kevin Alberts 
[ADD AccessRelation Match] "user"=Isaac, "permission"=Workshop 
[...]
[ADD AccessRelation Match] "user"=Isaac, "permission"=Office2 
Done!

Searching for Users without a role... 
[ADD RoleName Match] "role"=Director, "name"=Director 
[...]
[ADD RoleName Match] "role"=Guard, "name"=Guard 
Found user without role:"user"=Kevin Alberts
Done!

[Updated on: Mon, 20 April 2020 15:12]

Report message to a moderator

Re: Matches not send to change listener [message #1826184 is a reply to message #1826168] Mon, 20 April 2020 17:48 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan UjhelyiFriend
Messages: 379
Registered: July 2015
Senior Member
Hi Hans,

glad to hear you work with VIATRA again, and I am sorry that you notice so many problems during the work.

About the documentation, the method mentioned in the Javadoc was removed quite a few years ago, sorry for the confusion.

The case you mentioned is very strange and I don't have any idea what might be the problem. Can you maybe create a package that I could import into my VIATRA installation and check it out how it works - e.g. exporting the metamodel and the related viatra projects with a short description how to test the behaviour. The fact that you require adding a second listener to make it appear seems very strange to me, and it would be helpful to me if I don't have to create a reproducible test case from scratch.

Best regards,
Zoltán
Re: Matches not send to change listener [message #1826210 is a reply to message #1826184] Tue, 21 April 2020 08:22 Go to previous messageGo to next message
Hans van der Laan is currently offline Hans van der LaanFriend
Messages: 34
Registered: February 2020
Member
Hey Zoltán,

Ofcourse, I've uploaded the project and the metamodel to github: https://github.com/HansvdLaan/debug-viatra.
The metamodel can be found in the rbac-metamodel folder and the validator can be found in the rbacviatratest folder.
The repo isn't very organized at the moment, I want to make one nice single repo with maven but I haven't come around to do this yet.

It could also be that I'm not using APIs in the way they should be used. I'm just trying things out for now :)
At the moment, I'm working my way through VQL / the Query API. Next, I want to look at the EVM. Perhaps the EVM is more suited for this kind of logging.

On a small side note. I'm also reading up on some of the papers published on VIATRA. I've read: "Road to a reactive and incremental model transformation platform: three generations of the VIATRA framework" and
"Viatra 3: A Reactive Model Transformation Platform" thus far. I'm now reading "EMF-IncQuery: An integrated development environment for live model queries". As you can probably guess from the project on GitHub,
I'm doing research about incremental verification of physical access control systems. Are there any other papers you recommend reading about VIATRA / incremental consistency checking?
Re: Matches not send to change listener [message #1826242 is a reply to message #1826210] Tue, 21 April 2020 18:00 Go to previous messageGo to next message
Zoltan Ujhelyi is currently offline Zoltan UjhelyiFriend
Messages: 379
Registered: July 2015
Senior Member
Hi Hans,

thanks for the reproduction, it worked for me and I have managed to create a minimal reproduction and a corresponding bug report in https://bugs.eclipse.org/bugs/show_bug.cgi?id=562369 We will have a look at what the issue might be.

To be honest, for logging the output (if you are fine with some occasional temporary inconsistencies, such as a match getting removed and added if multiple elements are changed once), relying on match update listeners should work. However, I'd recommend skipping EVM and working with the transformation API (already mentioned in the tutorial) for this case, as there you can ensure that logging only happens in stable states (e.g. after a transaction was processed) and also you have control over the order of logging (e.g. you can make sure some type of events will get logged before others).



About the paper recommendation, I will ask one of my colleagues, as he has worked with similar things recently, and maybe he has some better recommendations I can get from the top of my head.

Best regards,
Zoltán
Re: Matches not send to change listener [message #1826383 is a reply to message #1826210] Fri, 24 April 2020 08:43 Go to previous messageGo to next message
Gabor Bergmann is currently offline Gabor BergmannFriend
Messages: 35
Registered: July 2009
Member
Hi Hans,

Hans van der Laan wrote on Tue, 21 April 2020 10:22

On a small side note. I'm also reading up on some of the papers published on VIATRA. I've read: "Road to a reactive and incremental model transformation platform: three generations of the VIATRA framework" and
"Viatra 3: A Reactive Model Transformation Platform" thus far. I'm now reading "EMF-IncQuery: An integrated development environment for live model queries". As you can probably guess from the project on GitHub,
I'm doing research about incremental verification of physical access control systems. Are there any other papers you recommend reading about VIATRA / incremental consistency checking?



Zoltán alerted me to your request on further Viatra-related papers, specifically relating to incremental verification and to access control.

I have the following two pointers to give.

1. We were involved in a line of research that applied Viatra to (non-physical) access control. Here is the main MODELS 2016 paper, and here is a workshop paper on making the computation live/incremental. There are new developments on incrementalizing these kinds of problems based on Differential Dataflow (an alternative technique for handling recursion), but they are not fully implemented or published yet.

2. As for complex incremental verification outside the domain of access control... we can implement static analysis of program code in Viatra, and use it to provide incremental feedback in an IDE! Here is the main paper at OOPSLA 2018. (The language frontend here is different from the usual VQL syntax, it is specifically geared for program verification, but it compiles to the same kind of Viatra queries.) Again, there are significant improvements in the works using Differential Dataflow; again, they are unfortunately not published yet.

3. I would really love to hear about what you are doing with Viatra and access control. :) Can you give me some pointers? Starting mid May, I will perhaps have enough time to read stuff again.

Cheers,
Gábor
Re: Matches not send to change listener [message #1826663 is a reply to message #1826383] Tue, 28 April 2020 13:16 Go to previous message
Hans van der Laan is currently offline Hans van der LaanFriend
Messages: 34
Registered: February 2020
Member
Hello Gábor,

Thank you very much for these pointers! Interesting to see you've also been working on access control.

I'm currently working on efficient authorization constraint verification (e.g. prerequisite, cardinality and separation of duty constraints). I'm doing this research in the R&D department of Nedap. They make soft- and hardware for physical access control systems.

Most tools recheck all constraints whenever the authorization policy changes. This is not very efficient. Through reasoning about the changes I hope reduce the amount of recalculations required. This is especially necessary when reasoning about temporal role-based access control.

... And that's when I came across Viatra... :)

The physical aspect of the problem is that this domain introduces new constraints. For example, the implicit assumption is (almost) always made that whenever you have access to an object, you can invoke this access. This assumption does hold in physical access control. Having the permission to access a door does not mean you can actually reach this door. Thus we want to check that the user can always invoke all granted permissions. Another example constraint is that a user should never get "stuck" inside the building: at all times, the user should be able to reach the exit.

When you have the time to read again, I can recommend checking out [2] and [3]. I've found them very insightful.

[2] is an extensive overview paper. They show which methods and tools have been used for access control / network policy analyses and provide a good conceptual model on what actually is policy analysis and what kind of analyses one might want to perform.
When I started writing my research proposal, Nedap had a lot of ideas/wishes. This paper helped put all the disconnected ideas/wishes into one framework and also showed us new possibilities. I've found this paper so good that I actually shared this paper with the manager of the department, which in turn shared it with the business team.

[3] presents an ecore-based access control model which (mostly) subsumes many popular RBAC extensions. They also present an exhaustive list of constraints found in the literature, and show how they can be expressed in OCL.


Kind regards,

Hans

[1] https://www.nedapsecurity.com/
[2] Methods and Tools for Policy Analysis (https://dl.acm.org/doi/pdf/10.1145/3295749)
[3] A Comprehensive Modeling Framework for Role-based Access Control Policies (https://people.svv.lu/bianculli/pubs/bbb-jss2015.pdf)

[Updated on: Tue, 28 April 2020 13:19]

Report message to a moderator

Previous Topic:How to import Viatra via Maven
Next Topic:Consistency Checking - Viatra
Goto Forum:
  


Current Time: Mon Nov 30 15:26:58 GMT 2020

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

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

Back to the top