New assignment to collection-type class field absent from flow program with Rascal, unlike to local variables - rascal

Consider the following Java code:
import java.util.LinkedList;
import java.util.List;
class Library {
List<String> loans = new LinkedList<>();
public List<String> searchUser(String name) {
List<String> usersFound = new LinkedList<>();
return loans;
}
}
and the following Rascal module:
module Mwe
import lang::java::flow::JavaToObjectFlow;
import lang::java::jdt::m3::AST;
import IO;
void m() {
ast = createAstFromEclipseFile(|project://test/src/test.java|, true);
fp = createOFG({ast});
print(fp);
}
The resulting flow program will be:
flowProgram({
attribute(|java+field:///Library/loans|),
method(|java+method:///Library/searchUser(java.lang.String)|,[|java+parameter:///Library/searchUser(java.lang.String)/scope(name)/scope(0)/name|]),
constructor(|java+constructor:///Library/Library()|,[])
},{
assign(|java+method:///Library/searchUser(java.lang.String)/return|,|id:///|,|java+field:///Library/loans|),
newAssign(|java+variable:///Library/searchUser(java.lang.String)/usersFound|,|java+class:///java/util/LinkedList|,|java+constructor:///java/util/LinkedList/LinkedList()|,[])
})
So, there is a new assignment of LinkedList to usersFound, but nothing comparable for loans. Why would that happen? Is that the intended behaviour?

Just checked the implementation, the field initializers are not included in the getStatements function (see lang::java::flow::JavaToObjectFlow on line 169). Similarly the static initializers of a class are ignored.
The best way forward would be to either report it as a bug, or fix it and turn it into a pull-request. (pull request is the quickest way to getting it fixed on unstable)
As a possible, yet work intensive workaround you rewrite the AST to put the field initializers inside all existing constructors (or add a constructor if there is none).

Related

Cannot import package in unit tests for a Jenkins Shared Library

I'm attempting to create unit tests for a JenkinsShared library using Gradle in order to run the test tasks.
I've followed this tutorial which upon conclusion one has a working test suite for a shared library for functions within the vars folder (with the unit tests in src/test/groovy/*Test.groovy).
However, in our internal shared jenkins library we followed a more object oriented style and isolated functionality into a package of classes in the format: src/org/company/*.groovy.
The problem arises when attempting to import said package into a unit test class. In the tutorial, the functions are imported using the loadScript method this method fails when loading a class which is dependent on another file.
Take the class:
package tests
import org.junit.*
import com.lesfurets.jenkins.unit.*
import static groovy.test.GroovyAssert.*
import org.company.UtilFactory
class UtilFactoryTest extends BasePipelineTest {
#Test
void testCall() {
def util = UtilFactory.getUtil("hello")
assertEquals true, true
}
}
src/org/company/UtilFactory.groovy
package org.company
class UtilFactory implements Serializable {
static Util instance
static Util getUtil(script=null) {
if (!(UtilFactory.instance)) {
if (!script) {
// Throws an exception if on the first call to getUtil the
// script parameter is null.
throw new ScriptUndefinedException("script parameter null on initial call to getUtil")
}
UtilFactory.instance = new Util(script)
}
return UtilFactory.instance
}
}
class ScriptUndefinedException extends Exception {
// Parameterless Constructor
public ScriptUndefinedException() {}
// Constructor that accepts a message
public ScriptUndefinedException(String message)
{
super(message);
}
}
Which gives me the exception:
jenkins-utilities/src/test/groovy/UtilFactoryTest.groovy: 7:
unable to resolve class org.company.UtilFactory
# line 7, column 1.
import org.company.UtilFactory
This may be more of a Gradle issue than a JenkinsShared Library. I've just spent a good portion of my day trying to figure out exactly what I'm doing wrong to no avail.
I would really appreciate any help to guide me in the right direction.
This library may be helpful getting your shared libraries to work in the unit test https://github.com/stchar/pipeline-sharedlib-testharness

Get declarations from an external source in Xtext

I have the following grammar:
Model: declarations += Declaration* statements += Statement*;
Declaration: 'Declare' name=ID;
Statement: 'Execute' what=[Declaration];
With that I can write simple scripts like:
Declare step_forward
Declare turn_right
Declare turn_left
Execute step_forward
Execute turn_left
Execute step_forward
Now I want that the java program provides all declarations, so that the script only contains the Execute statements. I read about IGlobalScopeProvider which seems to be the right tool for the job, but I have no idea how to add my data to it, and how to make Xtext use it.
So, how can I provide declarations from external to my grammar?
Update
My goal was somewhat unclear, so I try to make it more concrete. I want to keep the declarations as simple java objects, for instance:
List<Move> declarations = Arrays.asList(
new Move("step_forward"),
new Move("turn_right"),
new Move("turn_left"));
and the script should be:
Execute step_forward
Execute turn_left
Execute step_forward
I'm not really sure what you are asking for. After thinking about it, I cand derive th following possible questions:
1.) You want to split your script into two files. File a will only contain your declarations and File b then will only contain Statements. But any 'what' attribute will hold a reference to the declarations of File a.
This works out of the box with your grammar.
2.) You have any Java source code which provides a class which defines, for example a 'Declare Interface', and you want the 'what' attribute to reference to this interface or to classes which implement this interface.
Updated answer You should use Xbase within your language. There you can define that your 'what' attribute references to any Java type using the Xtypes rule 'JvmTypeReference'. The modifications you have to within your grammar are not that difficult, I think it could look this:
// Grammar now inherits from the Xbase grammar
// instead of the common terminals grammar
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
declarator=Declarator?
statements+=Statement*;
Declarator:
'Declare' name=ID;
Statement:
'Execute' what=JvmTypeReference;
The, you can refer to any Java type (Java API, any linked API, user-defined types) by adressing them with their qualified name. It would look like this:
Referring to JVM types look like this in an Xtext language. (Screenshot)
You can also validate whether the referenced JVM type is valid, e.g. implements a desired interface which I would define with one single, optional declarator in the model.
Referenced JVM type is checked whether it is a valid type. (Screenshot)
With Xbase it is very easy to infer a Java interface for this model element. Use the generated stub '...mydsl.MyDslJvmModelInferrer':
class MyDslJvmModelInferrer extends AbstractModelInferrer {
#Inject extension JvmTypesBuilder
#Inject extension TypeReferences
def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(
element.declaration.toInterface('declarator.' + element.declaration.name) [
members += it.toMethod("execute", TypesFactory.eINSTANCE.createJvmVoid.createTypeRef)[]
])
}
}
It derives a single interface, named individually with only one method 'execute()'.
Then, implement static checks like this, you should use the generated stub '...mydsl.validation.MyDslValidator' In my example it is very quick and dirty, but you should get the idea of it:
class MyDslValidator extends AbstractMyDslValidator {
#Check
def checkReferredType(Statement s) {
val declarator = (s.eContainer as Model).declaration.name
for (st : (s.what.type as JvmDeclaredType).superTypes) {
if (st.qualifiedName.equals('declarator.' + declarator)) {
return
}
}
(s.what.simpleName + " doesn't implement the declarator interface " + declarator).
warning(MyDslPackage.eINSTANCE.statement_What)
}
}
(I used the preferred Xtend programming language to implement the static checking!) The static check determines if the given JvmTypeReference (which is a Java class from your project) implements the declared interface. Otherwise it will introduce a warning to your dsl document.
Hopefully this will answer your question.
Next update: Your idea will not work that well! You could simply write a template with Xtend for that without using Xbase, but I cannot imagine how to use it in a good way. The problem is, I assume, you don't to generate the hole class 'Move' and the hole execution process. I have played around a little bit trying to generate usable code and seems to be hacky! Neverthess, here is my solution:
Xtext generated the stub '...mydsl.generator.MyDslGenerator' for you with the method 'void doGenerate'. You have to fill this method. My idea is the following: First, you generate an abstract and generic Executor class with two generic parameters T and U. My executor class then has an abstract method 'executeMoves()' with the return value T. If this should be void use the non-primitive 'Void' class. It holds your List, but of the generic type u which is defined as a subclass of a Move class.
The Move class will be generated, too, but only with a field to store the String. It then has to be derived. My 'MyDslGenerator' looks like that:
class MyDslGenerator implements IGenerator {
static var cnt = 0
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
cnt = 0
resource.allContents.filter(typeof(Model)).forEach [ m |
fsa.generateFile('mydsl/execution/Move.java', generateMove)
fsa.generateFile('mydsl/execution/Executor' + cnt++ + '.java', m.generateExecutor)
]
}
def generateMove() '''
package mydsl.execution;
public class Move {
protected String s;
public Move(String s) {
this.s = s;
}
}
'''
def generateExecutor(Model m) '''
package mydsl.execution;
import java.util.List;
import java.util.Arrays;
/**
* The class Executor is abstract because the execution has to implemented somewhere else.
* The class Executor is generic because one does not know if the execution has a return
* value. If it has no return value, use the not primitive type 'Void':
* public class MyExecutor extends Executor_i<Void> {...}
*/
public abstract class Executor«cnt - 1»<T, U extends Move> {
#SuppressWarnings("unchecked")
private List<U> declarations = Arrays.<U>asList(
«FOR Statement s : m.statements»
(U) new Move("«s.what.name»")«IF !m.statements.get(m.statements.size - 1).equals(s)»,«ENDIF»
«ENDFOR»
);
/**
* This method return list of moves.
*/
public List<U> getMoves() {
return declarations;
}
/**
* The executor class has to be extended and the extending class has to implement this
* method.
*/
public abstract T executeMoves();
}'''
}

Dart Can't get logging statements to compile

I'm trying to learn how to implement logging using the examples/tutorial in:
http://blog.dartwatch.com/2013/05/campaign-to-use-real-logging-instead-of.html#comment-form
But having imported the libraries this line in main will not compile because the class 'PrintHandler' is not recognized and Google has not been a help in this case. My server application consists of a main and three classes. I'm new at Dart. Below I've extracted the logging code that I added.
In what library is 'PrintHandler'? Is this a class I need to write?
library server;
import 'package:logging_handlers/logging_handlers_shared.dart';
import 'package:logging/logging.dart';
final _serverLogger = new Logger("server"); // top level logger
void main() {
Logger.root.onRecord.listen(new PrintHandler()); // default PrintHandler
_serverLogger.fine("Server created");
}
class A {
}
class B {
}
class C {
}
It looks like the class was changed to LogPrintHandler but the tutorial and documentation were not updated.

Clean up SAX Handler

I've made a SAX parser for parsing XML files with a number of different tags. For performance reasons, I chose SAX over DOM. And I'm glad I did because it works fast and good. The only issue I currently have is that the main class (which extends DefaultHandler) is a bit large and not very easy on the eyes. It contains a huge if/elseif block where I check the tag name, with some nested if's for reading specific attributes. This block is located in the StartElement method.
Is there any nice clean way to split this up? I would like to have a main class which reads the files, and then a Handler for every tag. In this Tag Handler, I'd like to read the attributes for that tag, do something with them, and then go back to the main handler to read the next tag which again gets redirected to the appropriate handler.
My main handler also has a few global Collection variables, which gather information regarding all the documents I parse with it. Ideally, I would be able to add something to those collections from the Tag Handlers.
A code example would be very helpful, if possible. I read something on this site about a Handler Stack, but without code example I was not able to reproduce it.
Thanks in advance :)
I suggest setting up a chain of SAX filters. A SAX filter is just like any other SAX Handler, except that it has another SAX handler to pass events into when it's done. They're frequently used to perform a sequence of transformations to an XML stream, but they can also be used to factor things the way you want.
You don't mention the language you're using, but you mention DefaultHandler so I'll assume Java. The first thing to do is to code up your filters. In Java, you do this by implementing XMLFilter (or, more simply, by subclassing XMLFilterImpl)
import java.util.Collection;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLFilterImpl;
public class TagOneFilter extends XMLFilterImpl {
private Collection<Object> collectionOfStuff;
public TagOneFilter(Collection<Object> collectionOfStuff) {
this.collectionOfStuff = collectionOfStuff;
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
if ("tagOne".equals(qName)) {
// Interrogate the parameters and update collectionOfStuff
}
// Pass the event to downstream filters.
if (getContentHandler() != null)
getContentHandler().startElement(uri, localName, qName, atts);
}
}
Next, your main class, which instantiates all of the filters and chains them together.
import java.util.ArrayList;
import java.util.Collection;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class Driver {
public static void main(String[] args) throws Exception {
Collection<Object> collectionOfStuff = new ArrayList<Object>();
XMLReader parser = XMLReaderFactory.createXMLReader();
TagOneFilter tagOneFilter = new TagOneFilter(collectionOfStuff);
tagOneFilter.setParent(parser);
TagTwoFilter tagTwoFilter = new TagTwoFilter(collectionOfStuff);
tagTwoFilter.setParent(tagOneFilter);
// Call parse() on the tail of the filter chain. This will finish
// tying the filters together before executing the parse at the
// XMLReader at the beginning.
tagTwoFilter.parse(args[0]);
// Now do something interesting with your collectionOfStuff.
}
}

Override default sequence name in Grails

How can I rename HIBERNATE_SEQUENCE? Methods for generating one sequence per table (and giving specific names to those sequences) are well-documented, but that's not what I'm looking for.
I don't mind having one sequence shared by all domain classes. I just need to give it an application-specific name.
There appears to be an open feature / enhancement request in the Hibernate JIRA to make this globally configurable: Make the default sequence name globally configurable. I believe, as a workaround, you would have to set the 'generator' attribute to the same name for all domain classes (defaults to hibernate_sequence) for every #Id field. See oracle sequence created.
As you hinted in your question, there might be a way to do this by subclassing your database dialect - as many have suggested for a sequence-per-table approach.
See id generator and DRY principle
Here is the code I used to set the sequence name.
First, the SequenceGenerator:
package com.foo;
import java.util.Properties;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.type.Type;
public class TableNameSequenceGenerator extends SequenceGenerator {
public static final String CUSTOM_SEQUENCE_NAME = "MYAPP_SEQUENCE"
public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
if(params.getProperty(SEQUENCE) == null || params.getProperty(SEQUENCE).length() == 0) {
String seqName = CUSTOM_SEQUENCE_NAME;
params.setProperty(SEQUENCE, seqName);
}
super.configure(type, params, dialect);
}
}
Next, the OracleDialect:
package com.foo;
import org.hibernate.dialect.Oracle10gDialect;
public class MyAppOracleDialect extends Oracle10gDialect {
public Class getNativeIdentifierGeneratorClass() {
return TableNameSequenceGenerator.class;
}
}
Last, DataSource.groovy needs to know about the dialect:
dataSource {
pooled = true
driverClassName = "oracle.jdbc.OracleDriver"
// username, password....
dialect='com.foo.MyAppOracleDialect'
}
Renaming the sequence is IMHO not directly possible but you might customize the identity as described on http://www.grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.5.2.4%20Custom%20Database%20Identity to generator:'native'. See http://docs.jboss.org/hibernate/stable/core/reference/en/html/mapping.html#mapping-declaration-id-generator for details.

Resources