Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gunnarmorling/4771731 to your computer and use it in GitHub Desktop.
Save gunnarmorling/4771731 to your computer and use it in GitHub Desktop.
public class Book {
@NotNull
private String title;
}
public class Library {
public void addBook(@NotNull @Valid Book book) { ... }
public void addAllBooks(@NotNull @Valid List<Book> books) { ... }
@NotNull
public String getLocation() { ... }
}
//Option #A1 (currently in draft): Have a single node representing a parameter or return value *and* the hosting method/constructor
//path to @NotNull on the "book" parameter of addBook()
Node(name=book, methodDescriptor=..., parameterDescriptor=..., constructorDescriptor=null)
//path to @NotNull on the "title" attribute of the book passed as argument to addBook()
Node(name=book, methodDescriptor=..., parameterDescriptor=..., constructorDescriptor=null)
Node(name=title, methodDescriptor=null, parameterDescriptor=null, constructorDescriptor=null)
//path to @NotNull on the "title" attribute of the 4th book in the list passed as argument to addAllBooks()
Node(name=books, methodDescriptor=..., parameterDescriptor=..., constructorDescriptor=null)
Node(name=title, methodDescriptor=null, parameterDescriptor=null, constructorDescriptor=null, inIterable=true, index=3)
//path to @NotNull on the return value of getLocation()
Node(name=???, methodDescriptor=..., parameterDescriptor=null, constructorDescriptor=null)
//Option #A2: Have individual node instances for the hosting method/constructor and parameter/return value
//path to @NotNull on the "book" parameter of addBook()
Node(name=addBook, methodDescriptor=..., parameterDescriptor=null, constructorDescriptor=null)
Node(name=book, methodDescriptor=null, parameterDescriptor=..., constructorDescriptor=null)
//path to @NotNull on the "title" attribute of the book passed as argument to addBook()
Node(name=addBook, methodDescriptor=..., parameterDescriptor=null, constructorDescriptor=null)
Node(name=book, methodDescriptor=null, parameterDescriptor=..., constructorDescriptor=null)
Node(name=title, methodDescriptor=null, parameterDescriptor=null, constructorDescriptor=null)
//path to @NotNull on the "title" attribute of the 4th book in the list passed as argument to addAllBooks()
Node(name=addAllBooks, methodDescriptor=..., parameterDescriptor=null, constructorDescriptor=null)
Node(name=books, methodDescriptor=null, parameterDescriptor=..., constructorDescriptor=null)
Node(name=title, methodDescriptor=null, parameterDescriptor=null, constructorDescriptor=null, inIterable=true, index=3)
//path to @NotNull on the return value of getLocation()
Node(name=getLocation, methodDescriptor=..., parameterDescriptor=null, constructorDescriptor=null)
Node(name=???, methodDescriptor=null, parameterDescriptor=null, constructorDescriptor=null)
//Option #B1 (currently in proposal): Have one single node type with all required attributes
interface Node {
String getName();
boolean isInIterable();
Integer getIndex();
Object getKey();
MethodDescriptor getMethodDescriptor();
ConstructorDescriptor getConstructorDescriptor();
ParameterDescriptor getParameterDescriptor();
//currently not in the proposal, but it seems actually more regular to me
//than representing return value constraints on the method descriptor
ReturnValueDescriptor getReturnValueDescriptor();
}
//Iterating over a Path
Path path = ...;
Iterator<Node> nodeIterator = path.iterator();
String methodName = null;
Class[] params = null;
boolean isCtr = false;
index arg;
while(nodeIterator.hasNext()) {
Node node = nodeIterator.next();
if (node.getMethodDescriptor() != null) {
methodName = node.getMethodDescriptor().getName();
isCtr = false;
List<ParameterDescriptor> paramsD = node.getMethodDescriptor().getParameterDescriptors();
int size = paramsD.size();
params = new Class[size];
for (int index = 0 ; index < size ; index++) {
params[index] = paramsD.get(index).getElementClass();
}
}
else if (node.getConstructorDescriptor() != null) {
methodName = node.getConstructorDescriptor().getName();
isCtr = true;
List<ParameterDescriptor> paramsD = node.getConstructorDescriptor().getParameterDescriptors();
int size = paramsD.size();
params = new Class[size];
for (int index = 0 ; index < size ; index++) {
params[index] = paramsD.get(index).getElementClass();
}
}
else {
// else deal with normal nodes for navigation
//say stored in a String[] and the leaf info for constraint in a dedicated structure
}
if(node.getParameterDescriptor() != null) {
arg = node.getParameterDescriptor().getIndex();
}
}
//use methodName, params, isCtr and arg to put an icon on the sidebar
Option #B2: Have a separate sub type for each "kind" of node. This requires option #A2, as we otherwise would need "combined" element kinds such as METHOD_PARAMETER, CONSTRUCTOR_PARAMETER etc. which doesn't seem nice
enum NodeKind {
BEAN, PROPERTY, METHOD, CONSTRUCTOR, PARAMETER, RETURN_VALUE;
}
interface Node {
String getName();
boolean isInIterable();
Integer getIndex();
Object getKey();
NodeKind getKind();
//should we offer something like this?
PropertyNode asPropertyNode();
MethodNode asMethodNode();
...
}
public interface MethodNode extends Node {
MethodDescriptor getMethodDescriptor();
}
//Iterating over Path
Path path = ...;
Iterator<Node> nodeIterator = path.iterator();
String methodName = null;
Class[] params = null;
boolean isCtr = false;
index arg;
while(nodeIterator.hasNext()) {
Node node = nodeIterator.next();
switch (node.getKind()) {
case METHOD:
MethodDescriptor descriptor = node.as(MethodNode.class).getMethodDescriptor();
methodName = descriptor.getName();
isCtr = false;
List<ParameterDescriptor> paramsD = descriptor.getParameterDescriptors();
int size = paramsD.size();
params = new Class[size];
for (int index = 0 ; index < size ; index++) {
params[index] = paramsD.get(index).getElementClass();
}
case CONSTRUCTOR:
ConstructorDescriptor descriptor = node.as(ConstructorNode.class).getConstructorDescriptor();
methodName = descriptor.getName();
isCtr = true;
List<ParameterDescriptor> paramsD = descriptor.getParameterDescriptors();
int size = paramsD.size();
params = new Class[size];
for (int index = 0 ; index < size ; index++) {
params[index] = paramsD.get(index).getElementClass();
}
case PARAMETER:
arg = node.as(ParameterNode.class).getParameterDescriptor().getIndex();
case RETURN_VALUE:
arg = -1; //convention in my special code
case ...
// else deal with normal nodes for navigation
//say stored in a String[] and the leaf info for constraint in a dedicated structure
}
}
//use methodName, params, isCtr and arg to put an icon on the sidebar
interface Node {
String getName();
boolean isInIterable();
Integer getIndex();
Object getKey();
Kind getKind();
<T extends Node> T as(Class<T> nodeType);
}
interface MethodNode extends Node {
List<Class<?>> getParameterTypes();
}
interface ConstructorNode extends Node {
List<Class<?>> getParameterTypes();
}
interface ReturnValueNode extends Node {
}
interface ParameterNode extends Node {
int getParameterIndex();
}
interface BeanNode extends Node {
}
interface PropertyNode extends Node {
}
//Iterating over Path
Path path = null;
Iterator<Node> nodeIterator = path.iterator();
String methodName = null;
Class<?>[] params = null;
boolean isCtr = false;
int arg;
while(nodeIterator.hasNext()) {
Node node = nodeIterator.next();
switch ( node.getKind() ) {
case METHOD:
MethodNode methodNode = node.as(MethodNode.class);
methodName = methodNode.getName();
isCtr = false;
params = methodNode.getParameterTypes().toArray( new Class<?>[methodNode.getParameterTypes().size()] );
break;
case CONSTRUCTOR:
ConstructorNode constructorNode = node.as(ConstructorNode.class);
methodName = constructorNode.getName();
isCtr = true;
params = constructorNode.getParameterTypes().toArray( new Class<?>[constructorNode.getParameterTypes().size()] );
break;
case PARAMETER:
arg = node.as(ParameterNode.class).getParameterIndex();
break;
case RETURN_VALUE:
arg = -1; //convention in my special code
break;
case ...
// else deal with normal nodes for navigation
//say stored in a String[] and the leaf info for constraint in a dedicated structure
}
}
//use methodName, params, isCtr and arg to put an icon on the sidebar
//Option #B3: Have one single node type with a reference to ElementDescriptor, have getKind() on ElementDescriptor
interface Node {
String getName();
boolean isInIterable();
Integer getIndex();
Object getKey();
ElementDescriptor getElementDescriptor();
}
//Iterating over Path
Path path = ...;
Iterator<Node> nodeIterator = path.iterator();
String methodName = null;
Class[] params = null;
boolean isCtr = false;
index arg;
while(nodeIterator.hasNext()) {
Node node = nodeIterator.next();
switch (node.getElementDescriptor().getKind()) {
case METHOD:
MethodDescriptor descriptor = node.getElementDescriptor().as(MethodDescriptor.class);
methodName = descriptor.getName();
isCtr = false;
List<ParameterDescriptor> paramsD = descriptor.getParameterDescriptors();
int size = paramsD.size();
params = new Class[size];
for (int index = 0 ; index < size ; index++) {
params[index] = paramsD.get(index).getElementClass();
}
case CONSTRUCTOR:
ConstructorDescriptor descriptor = node.getElementDescriptor().as(ConstructorDescriptor.class);
methodName = descriptor.getName();
isCtr = true;
List<ParameterDescriptor> paramsD = descriptor.getParameterDescriptors();
int size = paramsD.size();
params = new Class[size];
for (int index = 0 ; index < size ; index++) {
params[index] = paramsD.get(index).getElementClass();
}
case PARAMETER:
arg = node.getElementDescriptor().as(ParameterDescriptor.class).getIndex();
case RETURN_VALUE:
arg = -1; //convention in my special code
case ...
// else deal with normal nodes for navigation
//say stored in a String[] and the leaf info for constraint in a dedicated structure
}
}
//use methodName, params, isCtr and arg to put an icon on the sidebar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment