I'm doing semantic analysis of java codes. Some classes are as below:
ClassOrInterfaceDeclaration -> TypeDeclaration -> BodyDeclaration -> Node
The Node class is like this:
public abstract class Node {
private final int beginLine;
private final int beginColumn;
private Scope enclosingScope;
#Deprecated
public Node(int line, int column) {
this.beginLine = line;
this.beginColumn = column;
this.endLine = line;
this.endColumn = column;
}
public Node(int beginLine, int beginColumn, int endLine, int endColumn) {
this.beginLine = beginLine;
this.beginColumn = beginColumn;
this.endLine = endLine;
this.endColumn = endColumn;
}
public void setMyScope(Scope enclosingScope) {
this.enclosingScope = enclosingScope;
}
public Scope getMyScope() {
return enclosingScope;
}
public final int getBeginLine() {
return beginLine;
}
public final int getBeginColumn() {
return beginColumn;
} ... ...
Now, when I call these methods from an instance of ClassOrInterfaceDeclaration, any method is available except the setMyScope() and getMyScope(). Kinda a newbie. No idea why and how to fix it.
Codes of ClassOrInterfaceDeclaration is as below:
public final class ClassOrInterfaceDeclaration extends TypeDeclaration {
private final List<AnnotationExpr> annotations;
private final boolean isInterface;
private final List<TypeParameter> typeParameters;
private final List<ClassOrInterfaceType> extendsList;
private final List<ClassOrInterfaceType> implementsList;
public ClassOrInterfaceDeclaration(int line, int column, JavadocComment javaDoc, int modifiers, List<AnnotationExpr> annotations, boolean isInterface, String name, List<TypeParameter> typeParameters, List<ClassOrInterfaceType> extendsList, List<ClassOrInterfaceType> implementsList, List<BodyDeclaration> members) {
super(line, column, javaDoc, name, modifiers, members);
this.annotations = annotations;
this.isInterface = isInterface;
this.typeParameters = typeParameters;
this.extendsList = extendsList;
this.implementsList = implementsList;
}
public List<AnnotationExpr> getAnnotations() {
return annotations;
}
public boolean isInterface() {
return isInterface;
}
public List<TypeParameter> getTypeParameters() {
return typeParameters;
}
public List<ClassOrInterfaceType> getExtends() {
return extendsList;
}
public List<ClassOrInterfaceType> getImplements() {
return implementsList;
}
#Override
public <A> void accept(VoidVisitor<A> v, A arg) {
v.visit(this, arg);
}
#Override
public <R, A> R accept(GenericVisitor<R, A> v, A arg) {
return v.visit(this, arg);
}
}
TypeDeclaration and BodyDeclaration is similar. There is nothing about line, column or scope in them. However, while beginLine() and beginColumn() work well, the setMyScope(), getMyScope() don't. The latter two methods were added by me. I suspect that I have done something silly but can't figure out.
It seems like an issue where you are not able to reference the latest class version.
Possible issues :
code is not recompiled at all
there may be compilation error in other classes in the same src. Fix those and compile again.
You may have the jar file path in your classpath where the jar is not getting replaced with the latest one.
Please check if all these boxes are ticked. If the issue still persists, let us know
Related
Small question regarding the diamond operator and design pattern strategy for Java, please.
I would like to implement a very specific requirement:
there are some objects to store (in my example called MyThingToStore)
and the requirement is to store them with different kinds of data structures, for comparison.
Therefore, I went to try with a strategy pattern, where each of the strategies is a different way to store, I think this pattern is quite lovely.
The code is as follows:
public class MyThingToStore {
private final String name;
public MyThingToStore(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyThingToStore that = (MyThingToStore) o;
return Objects.equals(name, that.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "MyThingToStore{" +
"name='" + name + '\'' +
'}';
}
}
public class MyStorage {
private final StorageStrategy storageStrategy;
public MyStorage(StorageStrategy storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
public interface StorageStrategy {
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy{
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And this is working fine, very happy, especially tackled the requirement "easy to change the data structure to do the actual store".
(By the way, side question, if there is an even better way to do this, please let me know!)
Now, looking online at different implementations of strategy patterns, I see this diamond operator which I am having a hard time understanding:
MyThingToStore stays the same.
public class MyStorage {
private final StorageStrategy<MyThingToStore> storageStrategy; //note the diamond here
public MyStorage(StorageStrategy<MyThingToStore> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
#Override
public String toString() {
return "MyStorage{" +
"storageStrategy=" + storageStrategy +
'}';
}
}
public interface StorageStrategy<MyThingToStore> {
//note the diamond, and it will be colored differently in IDEs
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy<MyThingToStore> {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy<MyThingToStore> {
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy<MyThingToStore> storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And both versions will yield the same good result, also be able to answer requirements.
My question is: what are the differences between the version without a diamond operator, and the version with the diamond operator, please?
Which of the two ways are "better" and why?
While this question might appear to be "too vague", I believe there is a reason for a better choice.
I think the confusion comes from how you named type parameter for StorageStrategy in your 2nd example.
Let's name it T for type instead. T in this case is just a placeholder to express what type of objects your StorageStrategy can work with.
public interface StorageStrategy<T> {
void addToStore(T myThingToStore);
int getSize();
}
E.g.
StorageStrategy<MyThingToStore> strategy1 = // Initialization
StorageStrategy<String> strategy2 = // Initialization
strategy1.addToStore(new MyThingToStore("Apple"));
// This works fine, because strategy2 accepts "String" instead of "MyThingToStore"
strategy2.addToStore("Apple");
// Last line doesn't work, because strategy1 can only handle objects of type "MyThingToStore"
strategy1.addToStore("Apple");
To make it work properly, you need to change your different StorageStrategy implementations to also include the type parameter.
public class StorageUsingHashSetStrategy<T> implements StorageStrategy<T> {
private final Set<T> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(T myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
And lastly you also want to have a type paremeter for MyStorage
public class MyStorage<T> {
private final StorageStrategy<T> storageStrategy;
public MyStorage(StorageStrategy<T> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(T myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
Now you can create a MyStorage and can use it to store essentially any object into it and not just MyThingToStore. Whether that is something you want or not is up to you.
In the second code sample in the declaration of the interface StorageStrategy<MyThingToStore>, MyThingToStore is a Type Variable.
I.e. it's not the actual type, only a placeholder for a type, like T. The common convention is to use single-letter generic type variables (T, U, R, etc.), otherwise it might look confusing like in this case.
Note that in the class declarations, like:
public class StorageUsingArrayListStrategy
implements StorageStrategy<MyThingToStore>
MyThingToStore is no longer a type variable, but the name of the class MyThingToStore because in this case parameterized interface is implemented by a non-parameterized class (i.e. the actual type known to the compile is expected to be provided).
I have a bunch of classes like IntLogger, ShortLogger, StringLogger etc for all the types here.
The idea is to overload any methods for the Mutable types such that we log the value whenever it is updated.
These classes look like:
import org.apache.commons.lang3.mutable.MutableInt;
public class IntLogger extends MutableInt {
private final String loggerName;
private MutableInt value;
public IntLogger(String loggerName) {
this.loggerName = loggerName;
}
public IntLogger(String loggerName, int value) {
this.loggerName = loggerName;
this.value = new MutableInt(value);
logValue();
}
public void add(int operand) {
this.value.add(operand);
logValue();
}
// ...
public void setValue(int value) {
this.value = new MutableInt(value);
logValue();
}
private void logValue() {
System.out.println(this.value.toString()); // placeholder functionality
}
}
There are a lot that look exactly like IntLogger, such as FloatLogger which has the exact same methods, just replacing int with float and MutableInt with MutableFloat.
import org.apache.commons.lang3.mutable.MutableString;
public class StringLogger extends MutableObject<String> {
private final String loggerName;
private MutableString value;
public StringLogger(String loggerName) {
this.loggerName = loggerName;
}
public StringLogger(String loggerName, String value) {
this.loggerName = loggerName;
this.value = new MutableInt(value);
logValue();
}
public void setValue(String value) {
this.value = new MutableString(value);
logValue();
}
private void logValue() {
System.out.println(this.value); // placeholder functionality
}
}
This obviously doesn't need methods like add, subtract etc. so this one is simple.
I thought about using an abstract class with generics, but I can't seem to figure out how to use them given we extend from the Mutable types, so I can't do add on a MutableObject<Int> for example.
I thought I could make an abstract class NumberLogger which IntLogger, DoubleLogger etc will extend from, and write all the add etc methods in there using generic types. But again the Mutable issue arises
Any ideas?
I'm currently doing dev on an inherited Spring boot app, part of it is sending an API POST request with the boolean of whether a soccer match is finished or not (resulted). I noticed that the design of the class was such:
//parent class
public class Fixture {
private final FixtureType type;
private final Team homeTeam;
private final Team awayTeam;
public Fixture(#JsonProperty("type") final FixtureType type,
#JsonProperty("homeTeam") final Team homeTeam,
#JsonProperty("awayTeam") final Team awayTeam
) {
this.type = type;
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
}
public boolean isResulted() {
return false;
}
/*
other methods
*/
}
//child class
public class Result extends Fixture {
private final Outcome outcome;
public Result(#JsonProperty("type") final FixtureType type,
#JsonProperty("homeTeam") final Team homeTeam,
#JsonProperty("awayTeam") final Team awayTeam,
#JsonProperty("outcome") final Outcome outcome) {
super(type, homeTeam, awayTeam);
this.outcome = outcome;
}
#Override
public boolean isResulted() {
return true;
}
/*
other methods
*/
}
In the Swagger documentation, the request specifies that "resulted": true needs to be a field in the JSON POST request. Now I can add that field into the constructor, but that would mean changing a load of tests and code that calls this constructor. My solution was to call the isResulted() method in the constructor itself. I've never done this before, but this works. Is there any reason that this design below would create issues in the long run?
public class Result extends Fixture {
private final boolean resulted;
public Result (){
super();
resulted = isResulted();
}
#Override
#JsonProperty("resulted")
public boolean isResulted() {
return true;
}
}
I don't understand what's the purpose of having a private field that is not used anywhere. I'm also not sure I understand the problem you'd like to have solved.
There's a possible approach that is both more flexible and compatible with your previous code:
public class Result extends Fixture {
private final boolean resulted;
public Result (boolean resulted){
super();
this.resulted = resulted;
}
public Result (){
this(true); // sets the default value
}
#Override
#JsonProperty("resulted")
public boolean isResulted() {
return resulted;
}
}
I'm using spring data (mongoDb) and I've got my repository:
public interface StoriesRepository extends PagingAndSortingRepository<Story, String> {}
Then i have a controller:
#RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Page<StoryResponse>> getStories(Pageable pageable) {
Page<StoryResponse> stories = storiesRepository.findAll(pageable).map(StoryResponseMapper::toStoryResponse);
return ResponseEntity.ok(stories);
}
Everything works fine, but I can't consume my endpoint using RestTemplate getForEntity method:
def entity = restTemplate.getForEntity(getLocalhost("/story"), new TypeReference<Page<StoryResponse>>(){}.class)
What class should I provide to successfully deserialize my Page of entities?
new TypeReference<Page<StoryResponse>>() {}
The problem with this statement is that Jackson cannot instantiate an abstract type. You should give Jackson the information on how to instantiate Page with a concrete type. But its concrete type, PageImpl, has no default constructor or any #JsonCreators for that matter, so you can not use the following code either:
new TypeReference<PageImpl<StoryResponse>>() {}
Since you can't add the required information to the Page class, It's better to create a custom implementation for Page interface which has a default no-arg constructor, as in this answer. Then use that custom implementation in type reference, like following:
new TypeReference<CustomPageImpl<StoryResponse>>() {}
Here are the custom implementation, copied from linked question:
public class CustomPageImpl<T> extends PageImpl<T> {
private static final long serialVersionUID = 1L;
private int number;
private int size;
private int totalPages;
private int numberOfElements;
private long totalElements;
private boolean previousPage;
private boolean firstPage;
private boolean nextPage;
private boolean lastPage;
private List<T> content;
private Sort sort;
public CustomPageImpl() {
super(new ArrayList<>());
}
#Override
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
#Override
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
#Override
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
#Override
public int getNumberOfElements() {
return numberOfElements;
}
public void setNumberOfElements(int numberOfElements) {
this.numberOfElements = numberOfElements;
}
#Override
public long getTotalElements() {
return totalElements;
}
public void setTotalElements(long totalElements) {
this.totalElements = totalElements;
}
public boolean isPreviousPage() {
return previousPage;
}
public void setPreviousPage(boolean previousPage) {
this.previousPage = previousPage;
}
public boolean isFirstPage() {
return firstPage;
}
public void setFirstPage(boolean firstPage) {
this.firstPage = firstPage;
}
public boolean isNextPage() {
return nextPage;
}
public void setNextPage(boolean nextPage) {
this.nextPage = nextPage;
}
public boolean isLastPage() {
return lastPage;
}
public void setLastPage(boolean lastPage) {
this.lastPage = lastPage;
}
#Override
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
#Override
public Sort getSort() {
return sort;
}
public void setSort(Sort sort) {
this.sort = sort;
}
public Page<T> pageImpl() {
return new PageImpl<>(getContent(), new PageRequest(getNumber(),
getSize(), getSort()), getTotalElements());
}
}
I know this thread is a little old, but hopefully someone will benefit from this.
#Ali Dehghani's answer is good, except that it re-implements what PageImpl<T> has already done. I considered this to be rather needless. I found a better solution by creating a class that extends PageImpl<T> and specifies a #JsonCreator constructor:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.company.model.HelperModel;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import java.util.List;
public class HelperPage extends PageImpl<HelperModel> {
#JsonCreator
// Note: I don't need a sort, so I'm not including one here.
// It shouldn't be too hard to add it in tho.
public HelperPage(#JsonProperty("content") List<HelperModel> content,
#JsonProperty("number") int number,
#JsonProperty("size") int size,
#JsonProperty("totalElements") Long totalElements) {
super(content, new PageRequest(number, size), totalElements);
}
}
Then:
HelperPage page = restTemplate.getForObject(url, HelperPage.class);
This is the same as creating a CustomPageImpl<T> class but allows us to take advantage of all the code that's already in PageImpl<T>.
As "pathfinder" mentioned you can use exchange method of RestTemplate. However instead of passing ParameterizedTypeReference<Page<StoryResponse>>() you should pass ParameterizedTypeReference<PagedResources<StoryResponse>>(). When you get the response you could retrieve the content - Collection<StoryResponse>.
The code should look like this:
ResponseEntity<PagedResources<StoryResponse>> response = restTemplate.exchange(getLocalhost("/story"),
HttpMethod.GET, null, new ParameterizedTypeReference<PagedResources<StoryResponse>>() {});
PagedResources<StoryResponse> storiesResources = response.getBody();
Collection<StoryResponse> stories = storiesResources.getContent();
Apart from the content storiesResources holds page metadata and links too.
A more step-by-step explanation is available here: https://stackoverflow.com/a/46847429/8805916
If you use spring-cloud-openfeign you can use PageJacksonModule.
Just register PageJacksonModule in your object mapper:
final ObjectMapper mapper = new ObjectMapper()
mapper.registerModule(new PageJacksonModule());
If you looking at this thread, and if you try this answer
https://stackoverflow.com/a/44895867/8268335
You will meet the 2nd problem:
Can not construct instance of org.springframework.data.domain.Pageable
Then I find the perfect solution from here:
https://stackoverflow.com/a/42002709/8268335
I create the class RestPageImpl from the answer above and problem solved.
You can probably use exchange method of restTemplate and get the body from it..
Check the following answer https://stackoverflow.com/a/31947188/3800576.
This might help you
I have created a solution for optionals in Java.
public final class Optional<T> {
private final T reference;
private Optional(T reference) {
this.reference = reference;
}
public T get() {
if (!isPresent()) {
throw new IllegalStateException("Cannot retrieve reference when absent!");
}
return reference;
}
public boolean isPresent() {
return reference != null;
}
public static <T> Optional<T> of(T reference) {
return new Optional<T>(reference);
}
public static <T> Optional<T> absent() {
return of(null);
}
public static <T> Optional<T> fromNullable(#Nullable T nullableReference) {
return of(nullableReference);
}
}
But when I am using it in my production code, the compiler complains.
This is my production code:
public final class OnsetSequencer {
private final Onset onset;
private final Optional<EventManager> eventManager;
public OnsetSequencer(Onset onset, Optional<EventManager> eventManager) {
this.onset = onset;
this.eventManager = eventManager;
}
public OnsetSequencer(Onset onset) {
this(onset, Optional.absent());
}
public void sequence() {
boolean present = eventManager.isPresent();
if (present) {
eventManager.get().dispatchEvent(new OnsetBeginEvent(onset));
}
onset.begin();
if (present) {
eventManager.get().dispatchEvent(new OnsetEndEvent(onset));
}
onset.end();
}
}
The compiler complains at this(onset, Optional.absent()); saying: The constructor OnsetSequencer(Onset, Optional) is undefined
I have tried to fix the issue by changing it to this(onset, Optional<EventManager>.absent());
That syntax is wrong as well.
I am wondering how to fix this issue!
I think you want:
Optional.<EventManager>absent()
I've never liked the way of expressing type arguments for generic methods in Java, but such is life. See section 15.12 of the JLS for details.
You should be using:
Optional.<EventManager>absent()