Antlr4 - Getting name of matched rule - antlr4

I'm creating a relatively simple grammar which parses and breaks down strings into sub-components. A simplified version of the grammer is shown below
stmt: location type ID;
location :
location_A
| location_B
| location_C
;
location_A : 'LOCATION TOKEN 1';
location_B : 'LOCATION TOKEN 2';
location_C : 'LOCATION TOKEN 3';
Within my listener I have implemented ExitLocation to catch the token matched by this rule, but I would also like to extract the rule name of the sub-rule with which the token was matched (i.e. location_A/B/C).
Is it possible, from within the listener, to determine which sub-rule matched the token found?
Best Wishes
Dines Madsen

Alternative labels will help you here. Decorate all alternatives with a unique #name:
location
: location_A #alt1
| location_B #alt2
| location_C #alt3
;
and in your listener and visitor, there are enter- and exit-methods created for these labels (exitAlt1(...), exitAlt2(...), ...).

Another option is to assign the result of the subrules (which are by default rule contexts) to a local variable and check that in your listeners:
location:
value = location_A
| value = location_B
| value = location_C
;
LocationContext.value then contains the matched location rule.

I ended up simply grabbing the context name from the child node. As this information is only required for debugging purposes, it should be enough:
public override void ExitLocations([NotNull] TagParserParser.LocationsContext context)
{
try
{
this.myLocationToken = context.GetText();
this.myLocationRule = context.children[0].GetType().Name;
}
catch (Exception)
{
}
}
Thank you for your suggestions.

Related

How to map undefined amount of path parameters to request parameters in Ocpsoft Rewrite?

Currently I´m trying the following JSF - Lib:
https://www.ocpsoft.org/rewrite/examples/
I have the following issue:
I have a page:
/page.jsf
In my page I have more then only one parameter.
E.g. I have:
- parameter1
- parameter2
String parameter1 = FacesContext.getCurrentInstance().getExternalContext()
.getRequestParameterMap().get("parameter1");
String parameter2 = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap()
.get("parameter2");
Currently I understood I can add this in my UrlConfigProvider class:
.addRule(Join.path("/page/{parameter1}").to("/portal/mypage.jsf")
.withInboundCorrection())
This is working for one parameter.
But how can I do this for multiple parameter, so the URL is then:
/page/{parameter1}/{parameter2}
....
Any ideas?
The rewrite API doesn't bring a native solution for this problem.
Kick-Off Example
.addRule()
.when(/* your condition */)
.perform(new HttpOperation() {
#Override
public void performHttp(HttpServletRewrite httpServletRewrite, EvaluationContext evaluationContext) {
// this is the default wrapper
HttpRewriteWrappedRequest request = ((HttpRewriteWrappedRequest) httpServletRewrite.getRequest());
// get the uri (example: '/index/p1/p2')
String uri = httpServletRewrite.getRequest().getRequestURI();
// split by slash
String[] split = uri.split("/");
// this is example specific
// split value 0 is empty and split value 1 is the page (e.g. 'index')
// for every folder increment the index
// for '/pages/index' the start index should 3
for (int i = 2; i < split.length; i++) {
String s = split[i];
// the request parameter is by default an immutable map
// but this returns a modifiable
request.getModifiableParameters().put("prefix" + (i - 1), new String[]{s});
}
}
});
Explanation
The only important piece is the HttpOperation. By default the ServletRequest is wrapped in a HttpRewriteWrappedRequest.
The default HttpServletRequest doesn't allow to change the parameters once they were initialized. The method getParameterMap() returns an immutable map.
getParameterMap() of the HttpRewriteWrappedRequest also returns an immutable map. But getModifiableMap() returns obviously a modifiable map.
The rest should be self-explanatory.
See Also
Ocpsoft: How to modify parameters
Modify request parameter with servlet filter

Get users information when creating a customer

I'm trying to create a Prestashop Module which when a user is created, I can get all his information automatically using ActionCustomerAccountAdd, this event return ($params), but I don't know the structure of the object params for getting the data needed
I tried to create hookActionCustomerAccountAdd which get params, I was able to get just the email of the customer $params['newCustomer']->email, but I can't get the first name and last name and the password
// Will be executed each times actionCustomerAccountAdd is triggered
public function hookActionCustomerAccountAdd($params)
{
// $params is an array set by PrestaShop which contains the
// hook data (here, the customer details
$this->CustomerAdd($params['newCustomer']->email);
/* $json_output = json_decode($params,true);
var_dump($json_output) ;
echo "Works";
*/
}
public function CustomerAdd($mail){
$myObj->userx->UserID = 0;
$myObj->userx->Username = "NameUser";
$myObj->userx->Password ="Password";
$myObj->userx->Fname ="Fname";
$myObj->userx->Lname= "Lname";
$myObj->userx->Mail= $mail;
$myObj->username= "evdokimosk";
$myObj->password="123425";
}
I expect to get all data I need like first name, last name but I don't know what is inside the $params
$params['newCustomer'] is the object of the client, so you can retrieve customer information: :
$firstname = $params['newCustomer']->firstname;
$lastname = $params['newCustomer']->lastname;
....
Regards

How to skip a field during map stage?

I'm having list of employee objects - List
I need to convert it into list of employee transfer objects - List
Assume a field "password" exist in both the classes.
In few cases i need the password needs to be included from Employee → EmployeeDTO
In few cases i don't need the password and want to be excluded from Employee - EmployeeDTO.
Sample Code Snippet:
List<Employee> employees = employeeRepository.findAll();
// Define the target type
Type targetListType = new TypeToken<List<EmployeeDTO>>() {}.getType();
List<EmployeeDTO> employeeDTOs = modelMapper.map(employees, targetListType);
Please let me know how to skip the fields on mapping/copying.
Take a look the official user manual of Conditional Mapping.
In brief:
You would need to add a new Mapping and use a Condition. Your source and destionation would be:
Source: Employee
Destination: EmployeeDto
First create and custom your Condition. It would be something like this:
Condition<?, ?> isNotZero = new Condition<PersonDTO, Employee>() {
public boolean applies(MappingContext<PersonDTO, Employee> context) {
//Your conidition
return context.getSource().getEmployeeId() != 0;
}
};
Then add Mapping and use the condition:
modelMapper.addMappings(new PropertyMap<PersonDTO, Person>() {
protected void configure() {
when(isNotZero).map(source).setEmployee(null);
}
});
You can find this examples in the ModelMapper GitHub repository. The author has done few more and are well explained:
Link to above example
Here is how I skip fields during the mapping stage:
ModelMapper modelMapper = new ModelMapper();
modelMapper.typeMap(EmployeeDTO.class,Employee.class).addMappings(mapper -> {
mapper.skip(Employee::setPassword);
});

Grails search/filter multiple parameters - controller logic

Using Grails (or hibernate), I was wanting to know if there is a specific design pattern or method we should be using when implementing a SEARCH of our domain.
For example, on my website, I want to be able to filter(or search) by multiple properties in the domain.
EG: For I have a page which displays a list of HOTELS. When I submit a search form, or if a user clicks "filter by name='blah'", when I enter the controller I get the following:
Domain
String name
String location
Controller
if(params.name && params.reference) {
// Find name/reference
} else if(params.name) {
// Find name
} else if(params.reference) {
// Find reference
} else {
// Find all
}
As you can understand, if there are more properties in the domain to search/filter, the longer the controller gets.
Any help. Please note, I do not want to use the 'searchable' plugin, as this is too complex for my needs.
I would embed these in a named query in the Domain class itself. For example:
Class Hotel {
String name
String city
String country
boolean isNice
static namedQueries = {
customSearch { p ->
if (p?.name) eq('name', p.name)
if (p?.city) eq('name', p.city)
if (p?.country) eq('name', p.country)
if (p?.isNice != null) eq('isNice', p.isNice)
}
}
}
Then later in a controller somewhere ...
def results = Hotel.customSearch(params)
Of course this is a very simple example, but you can expand on it using the same named query or even adding others and chaining them together.

Retrieve Current ID Crm Online

Entity title = new Entity();
title = service.Retrieve("incident",((Guid)((Entity)context.InputParameters["Target"]).Id), new ColumnSet("title"));
I am using this code to get the current id of an Incident while i'am closing it!
But received this error :
Unexpected exception from plug-in (Execute): FecharIncidente.Plugins.PostIncidenteClose: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
One of my mates uses exactly the same code and is working on his crm !
Some help !?!
Apparently your InputParameters collection doesn't have a "Target" key value. Check that the request that you're using has a "Target" InputParameter.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
title = service.Retrieve("incident", ((Entity)context.InputParameters["Target"]).Id, new ColumnSet("title"));
Bet you "Target" in not Contained in InputParameters, resulting in KeyNotFoundException - "The given key was not present in the dictionary."
your can check for Target like Daryl explained or use the context available from the workflow rather like so ...
protected override void Execute(CodeActivityContext executionContext)
{
// Create the context
var context = executionContext.GetExtension<IWorkflowContext>();
var title = new Entity();
//context.PrimaryEntityName - should hold string incident
//context.PrimaryEntityId - should hold your guid
title = service.Retrieve(context.PrimaryEntityName, context.PrimaryEntityId, new ColumnSet("title"));
}

Resources