Resolve a type in a context - java

I have a Spring boot project and I want to parse it and file the dependencies between classes I am using the JavaSymbolSolver to find out the Class Name
public static void main(String[] args) throws Exception {
Set<Map<String, Set<String>>> entries = new HashSet<>();
String jdkPath = "/usr/lib/jvm/java-11-openjdk-amd64/";
List<File> projectFiles = FileHandler.readJavaFiles(new File("/home/dell/MySpace/Tekit/soon-back/src/main"));
CombinedTypeSolver combinedSolver = new CombinedTypeSolver
(
new JavaParserTypeSolver(new File("/home/dell/MySpace/Tekit/soon-back/src/main/java/")),
new JavaParserTypeSolver(new File(jdkPath)),
new ReflectionTypeSolver()
);
JavaSymbolSolver symbolSolver = new JavaSymbolSolver(combinedSolver);
StaticJavaParser.getConfiguration().setSymbolResolver(symbolSolver);
CompilationUnit cu = null;
try {
cu = StaticJavaParser.parse(projectFiles.get(7));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
List<ClassOrInterfaceDeclaration> classes = new ArrayList<>();
TypeDeclarationImp typeDeclarationImp = new TypeDeclarationImp();
typeDeclarationImp.visit(cu, classes);
Set<String> collect = classes.stream()
.map(classOrInterfaceDeclaration -> {
List<MethodCallExpr> collection = new ArrayList<>();
MethodInvocationImp methodInvocationImp = new MethodInvocationImp();
classOrInterfaceDeclaration.accept(methodInvocationImp, collection);
return collection;
})
.flatMap(Collection::stream)
.map(methodCallExpr -> {
return methodCallExpr
.getScope()
.stream()
.filter(Expression::isNameExpr)
.map(Expression::calculateResolvedType)
.map(ResolvedType::asReferenceType)
.map(ResolvedReferenceType::getQualifiedName)
.map(s -> s.split("\\."))
.map(strings -> strings[strings.length - 1])
.collect(Collectors.toSet());
})
.filter(expressions -> expressions.size() != 0)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
collect.forEach(System.out::println);
}
I am facing this issue
Exception in thread "main" UnsolvedSymbolException{context='SecurityContextHolder', name='Solving SecurityContextHolder', cause='null'}
could you tell me if it is necessary to indicate all the libraries used by the project to parse it or there is another way for that

It's not entirely correct. If you only want to traverse the AST you don't need to provide project dependencies but if you want for example to know the type of a variable you must use the symbol solver and declare all the dependencies of the project to it.
Furthermore Javaparser can recover from parsing error (see https://matozoid.github.io/2017/06/11/parse-error-recovery.html)

Related

IFile.getFile is case sensitive

Say my workspace has certain files in the root folder like foo.xml, foo1.xml, foo2.xml, foo3.xml.
final List<String> configFiles = new ArrayList<>();
configFiles.add("foo.xml");
configFiles.add("foo1.xml");
configFiles.add("Foo2.xml");
final List<IFile> iFiles = configFiles.stream()
.map(project::getFile)
.filter(IFile::exists)
.collect(Collectors.toList());
When I do a getFile on the project, IFile expects a case sensitive fileName, say there is foo2.xml in my workspace and I try to access Foo2.xml, I don't get the file.
How can I get files regardless of the case ?
I don't think there is a simple way.
You could get call members() on the project:
IResource [] members = project.members();
and then match the member names using equalsIgnoreCase:
private IFile findFile(IResource [] members, String name)
{
for (IResource member : members) {
if (name.equalsIgnoreCase(member.getName())) {
if (member instanceof IFile) {
return (IFile)member;
}
return null;
}
}
return null;
}
so the stream would be:
final List<IFile> iFiles = configFiles.stream()
.map(file -> findFile(members, file))
.filter(Objects::nonNull)
.collect(Collectors.toList());

How to properly construct Akka Graph

I want to create a graph that has a source and that source is linked to a broadcast which fanout through two flows and then the output is zipped to a sink.
I did almost everything, but I have two problems:
The builder is not accepting my FanIn shape
I am providing a sink but it is required a shape sink and I don't know how to get that
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("test");
ActorMaterializer materializer = ActorMaterializer.create(system);
Source<Integer, NotUsed> source = Source.range(1, 100);
Flow<Integer, Integer, NotUsed> flow1 = Flow.of(Integer.class).map(i -> i + 1);
Flow<Integer, Integer, NotUsed> flow2 = Flow.of(Integer.class).map(i -> i * 2);
Sink<List<Integer>, CompletionStage<Integer>> sink = Sink.fold(0, ((arg1, arg2) -> {
int value = arg1.intValue();
for (Integer i : arg2) {
value += i.intValue();
}
return value;
}));
RunnableGraph<Integer> graph = RunnableGraph.fromGraph(GraphDSL.create(
(builder) -> {
UniformFanOutShape fanOutShape = builder.add(Broadcast.create(2));
UniformFanInShape fanInShape = builder.add(Zip.create());
return builder.from(builder.add(source))
.viaFanOut(fanOutShape)
.via(builder.add(flow1))
.via(builder.add(flow2))
.viaFanIn(fanInShape)
.to(sink);
}
));
}
any help is appreciated
You are failing to map the out ports from broadcast to the specific sub flows (flow1 and flow2) and similarly you need to map the specific flows (flow1 and flow2) coming together in zip stage to the specific port of a zip stage.
Also i think it is not clear what is expected from the flow you are writing. zip stage will return you a tuple (int, int), so output of zip in the stream would lead to stream of tuples. But your sink which is supposed to be added after zip does not accept a stream of tuples but stream of Integers
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("test");
ActorMaterializer materializer = ActorMaterializer.create(system);
Source<Integer, NotUsed> source = Source.range(1, 100);
Flow<Integer, Integer, NotUsed> flow1 = Flow.of(Integer.class).map(i -> i + 1);
Flow<Integer, Integer, NotUsed> flow2 = Flow.of(Integer.class).map(i -> i * 2);
//create a new zip stage which accepts
//Zip<?, ?, ?> zip1 =
final FanInShape2<Integer, Integer, Pair<Integer, Integer>> zip = builder.add(Zip.create());
Sink<List<Integer>, CompletionStage<Integer>> sink = Sink.fold(0, ((arg1, arg2) -> {
int value = arg1.intValue();
for (Integer i : arg2) {
value += i.intValue();
}
return value;
}));
RunnableGraph<Integer> graph = RunnableGraph.fromGraph(GraphDSL.create(flow1, flow2, sink,
(builder, flow1, flow2, sink) -> {
UniformFanOutShape fanOutShape = builder.add(Broadcast.create(2));
UniformFanInShape fanInShape = builder.add(Zip.create());
builder.from(builder.add(source))
.viaFanOut(fanOutShape)
builder
.from(broadcast.out(0))
.via(builder.add(flow1))
.toInlet(zip.in0());
builder
.from(broadcast.out(1))
.via(builder.add(flow2))
.toInlet(zip.in1());
builder
.from(zip.out()).toInlet(sink)
}
));
}
You can check the below link for more examples.
https://github.com/Cs4r/akka-examples/blob/master/src/main/java/cs4r/labs/akka/examples/ConstructingGraphs.java

Java Iterators and Streams

I am trying to convert a loop that I have made into Java streams, though the code uses iterators and I am finding it hard to convert it into readable code.
private void printKeys() throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
// read a json file
ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(classLoader.getResource("AllSets.json"));
Set<String> names = new HashSet<>();
// loop through each sub node and store the keys
for (JsonNode node : root) {
for (JsonNode cards : node.get("cards")) {
Iterator<String> i = cards.fieldNames();
while(i.hasNext()){
String name = i.next();
names.add(name);
}
}
}
// print each value
for (String name : names) {
System.out.println(name);
}
}
I have tried the following though I feel like its not going the right way.
List<JsonNode> nodes = new ArrayList<>();
root.iterator().forEachRemaining(nodes::add);
Set<JsonNode> cards = new HashSet<>();
nodes.stream().map(node -> node.get("cards")).forEach(cards::add);
Stream s = StreamSupport.stream(cards.spliterator(), false);
//.. unfinished and unhappy
You can find the Json file I used here: https://mtgjson.com/json/AllSets.json.zip
Be warned its quite large.
You can do most of the things in one swoop, but it's a shame this json api does not support streams better.
List<JsonNode> nodes = new ArrayList<>();
root.iterator().forEachRemaining(nodes::add);
Set<String> names = nodes.stream()
.flatMap(node -> StreamSupport.stream(
node.get("cards").spliterator(), false))
.flatMap(node -> StreamSupport.stream(
((Iterable<String>) () -> node.fieldNames()).spliterator(), false))
.collect(Collectors.toSet());
Or with Patrick's helper method (from the comments):
Set<String> names = stream(root)
.flatMap(node -> stream(node.get("cards")))
.flatMap(node -> stream(() -> node.fieldNames()))
.collect(Collectors.toSet());
...
public static <T> Stream<T> stream(Iterable<T> itor) {
return StreamSupport.stream(itor.spliterator(), false);
}
And printing:
names.stream().forEach(System.out::println);
If you provide 'json' file to us, it will be very useful.
At least now, I can make some suggestions to you:
Set<JsonNode> cards = new HashSet<>();
nodes.stream().map(node -> node.get("cards")).forEach(cards::add);
Replace with:
Set<JsonNode> cards = nodes.stream().map(node -> node.get("cards")).collect(Collectors.toSet());
for (String name : names) {
System.out.println(name);
}
Replace with:
names.forEach(System.out::println);
Replace
Set<JsonNode> cards = new HashSet<>();
with
List<JsonNode> cards = new ArrayList<>();
Remove
Stream s = StreamSupport.stream(cards.spliterator(), false);
Then add below lines
cards.stream().forEach( card -> {
Iterable<String> iterable = () -> card.fieldNames();
Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);
targetStream.forEach(names::add);
});
names.forEach(System.out::println);

Scala vs Java Streaming: Scala prints nothing, Java works

I'm doing a comparison between Scala vs Java Reactive Spec implementations using akka-stream and RxJava, respectively. My use case is a simplistic grep: Given a directory, a file filter and a search text, I look in that directory for all matching files that have the text. I then stream the (filename -> matching line) pair.
This works fine for Java but for Scala, nothing is printed. There's no exception but no output either.
The data for the test is downloaded from the internet but as you can see, the code can easily be tested with any local directory as well.
Scala:
object Transformer {
implicit val system = ActorSystem("transformer")
implicit val materializer = ActorMaterializer()
implicit val executionContext: ExecutionContext = {
implicitly
}
import collection.JavaConverters._
def run(path: String, text: String, fileFilter: String) = {
Source.fromIterator { () =>
Files.newDirectoryStream(Paths.get(path), fileFilter).iterator().asScala
}.map(p => {
val lines = io.Source.fromFile(p.toFile).getLines().filter(_.contains(text)).map(_.trim).to[ImmutableList]
(p, lines)
})
.runWith(Sink.foreach(e => println(s"${e._1} -> ${e._2}")))
}
}
Java:
public class Transformer {
public static void run(String path, String text, String fileFilter) {
Observable.from(files(path, fileFilter)).flatMap(p -> {
try {
return Observable.from((Iterable<Map.Entry<String, List<String>>>) Files.lines(p)
.filter(line -> line.contains(text))
.map(String::trim)
.collect(collectingAndThen(groupingBy(pp -> p.toAbsolutePath().toString()), Map::entrySet)));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}).toBlocking().forEach(e -> System.out.printf("%s -> %s.%n", e.getKey(), e.getValue()));
}
private static Iterable<Path> files(String path, String fileFilter) {
try {
return Files.newDirectoryStream(Paths.get(path), fileFilter);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
Unit test using Scala Test:
class TransformerSpec extends FlatSpec with Matchers {
"Transformer" should "extract temperature" in {
Transformer.run(NoaaClient.currentConditionsPath(), "temp_f", "*.xml")
}
"Java Transformer" should "extract temperature" in {
JavaTransformer.run(JavaNoaaClient.currentConditionsPath(false), "temp_f", "*.xml")
}
}
Dang, I forgot that Source returns a Future, which means the flow never ran. #MrWiggles' comment gave me a hint. The following Scala code produces equivalent result as the Java version.
Note: The code in my question didn't close the DirectoryStreamwhich, for directories with a large number of files, caused a java.io.IOException: Too many open files in system. The code below closes the resources up properly.
def run(path: String, text: String, fileFilter: String) = {
val files = Files.newDirectoryStream(Paths.get(path), fileFilter)
val future = Source(files.asScala.toList).map(p => {
val lines = io.Source.fromFile(p.toFile).getLines().filter(_.contains(text)).map(_.trim).to[ImmutableList]
(p, lines)
})
.filter(!_._2.isEmpty)
.runWith(Sink.foreach(e => println(s"${e._1} -> ${e._2}")))
Await.result(future, 10.seconds)
files.close
true // for testing
}

BeanUtils copyProperties to copy Arraylist

I know that BeanUtils can copy a single object to other.
Is it possible to copy an arraylist.
For example:
FromBean fromBean = new FromBean("fromBean", "fromBeanAProp", "fromBeanBProp");
ToBean toBean = new ToBean("toBean", "toBeanBProp", "toBeanCProp");
BeanUtils.copyProperties(toBean, fromBean);
How to achieve this?
List<FromBean > fromBeanList = new ArrayList<FromBean >();
List<ToBean > toBeanList = new ArrayList<ToBean >();
BeanUtils.copyProperties(toBeanList , fromBeanList );
Its not working for me. Can any one please help me.
Thanks in advance.
If you have a list origin with data and list destination empty, the solution is:
List<Object> listOrigin (with data)
List<Object> listDestination= new ArrayList<Object>();
for (Object source: listOrigin ) {
Object target= new Object();
BeanUtils.copyProperties(source , target);
listDestination.add(target);
}
If you have two lists of equals size then you can do the following
for (int i = 0; i < fromBeanList.size(); i++) {
BeanUtils.copyProperties(toBeanList.get(i), fromBeanList.get(i));
}
What you can do is to write your own generic copy class.
class CopyVector<S, T> {
private Class<T> targetType;
CopyVector(Class<T> targetType) {
this.targetType = targetType;
}
Vector<T> copy(Vector<S> src) {
Vector<T> target = new Vector<T>();
for ( S s : src ) {
T t = BeanUtils.instantiateClass(targetType);
BeanUtils.copyProperties(s, t);
target.add(t);
}
return target;
}
}
A step further would also be to make the List type generic - this assumes you want to copy Vectors.
you can try something like this
for(int i=0; i<fromBeanList.size(); i++){
BeanUtils.copyProperties(toBeanList.get(i) , fromBeanList.get(i) );
}
Hope this helps..
Oops it is already explained by someone now..
anyways try it.
BeanUtils.copyProperties, It only copy the property of same name. So, In case of ArrayList you can't do that.
According to docs:
Copy property values from the origin bean to the destination bean for
all cases where the property names are the same.
In spring BeanUtils.copyProperties, arguments are just opposite than apache commons lib
for(FromBean fromBean: fromBeanList) {
if(fromBean != null) {
ToBean toBean = new ToBean();
org.springframework.beans.BeanUtils.copyProperties(fromBean, toBean);
toBeanList.add(toBean);
}
}
public List<"ToBean"> getAll()
{
create an empty list of the Target folder
List<'ToBean>' toBeanList = new ArrayList<'ToBean'>();
Create a empty object of Target folder
ToBean toBean = new ToBean();
List<'FromBean > fromBeanList = beanRepository.findAll();
//Iterate Src Bean
for(fromBean : fromBeanList)
{
BeanUtils.copyProperties(fromBean , toBean );
toBeanList .add(toBean );
}
return toBeanList ;
}
What i used just now :
public static List<?\> copyPropertiesArray(List<?\> source, List<?\> destination,Class<?\> destinationClass) throws CopyPropertiesException {
try {
//the destination size must be the same as the source size and also it must be typed correctly (thus the need for the 3rd argument)
destination=Collections.nCopies(source.size(),destinationClass.newInstance()); //initialize the desination list to same size as the source
for (int i = 0; i < source.size(); i++) {
BeanUtils.copyProperties(destination.get(i), source.get(i));
}
return destination;
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
throw new Exception(e.getMessage());
}
}

Categories

Resources