com.javanut.pronghorn.pipe.proxy.PipeInvokeHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pronghorn-pipes Show documentation
Show all versions of pronghorn-pipes Show documentation
Ring buffer based queuing utility for applications that require high performance and/or a small
footprint. Well suited for embedded and stream based processing.
package com.javanut.pronghorn.pipe.proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
public class PipeInvokeHandler {
private static final Logger log = LoggerFactory.getLogger(PipeInvokeHandler.class);
protected final int MAX_METHODS = 1024;//based on how the key hash is built, do not change
private final int c1;
private final int c2;
private final int c3;
protected PipeInvokeHandler(final Method[] methods) {
//Compute the shortest name and
//computed the leading chars that all match
int minMethodNameLength = Integer.MAX_VALUE;
int leadingMatchingChars = Integer.MAX_VALUE;
int j = methods.length;
String lastName = null;
while (--j>=0) {
Method method = methods[j];
ProngTemplateField fieldAnnotation = method.getAnnotation(ProngTemplateField.class);
if (null!=fieldAnnotation) {
String methodName = method.getName();
minMethodNameLength = Math.min(minMethodNameLength, methodName.length());
if (null!=lastName) {
int limit = Math.min(methodName.length(), lastName.length());
int i = 0;
while (i=0) {
Method method1 = methods[m];
if (null!=method1.getAnnotation(ProngTemplateField.class)) {
String methodName = method1.getName();
//scan all the method names down from this one to check for another with the same length
int k = m;
while (--k>=0) {
Method method2 = methods[k];
if (null!=method2.getAnnotation(ProngTemplateField.class)) {
String methodName2 = method2.getName();
if (namesBuildSameKey(methodName2, methodName, tempC1, tempC2, tempC3, cursor)) {
//throws if nothing can be done
switch (cursor) {
case 0:
tempC1 = addColumnToDistinquishNames(methodName2, methodName, cursor, leadingMatchingChars, minMethodNameLength);
break;
case 1:
tempC2 = addColumnToDistinquishNames(methodName2, methodName, cursor, leadingMatchingChars, minMethodNameLength);
break;
case 2:
tempC3 = addColumnToDistinquishNames(methodName2, methodName, cursor, leadingMatchingChars, minMethodNameLength);
break;
default:
throw new UnsupportedOperationException("Method names are too similar. Every annotated field must have a different field name.");
}
cursor++;
}
}
}
}
}
this.c1 = tempC1;
this.c2 = tempC2;
this.c3 = tempC3;
log.trace("All methods share the first {} chars in common", leadingMatchingChars);
log.trace("Shortest method names is {} chars", minMethodNameLength);
log.trace("With length these additional char positions make name key unique {}, {}, {}",tempC1,tempC2,tempC3);
}
private int addColumnToDistinquishNames(String methodName2, String methodName, int cursor, int leadingMatchingChars, int minMethodNameLength) {
if (cursor>=3 || methodName.equals(methodName2)) {
//can't add any more columns, perhaps we should use 4 of these per int or look at using a long for the value.
throw new UnsupportedOperationException("Method names are too similar. Every annotated field must have a different field name.");
}
int i = minMethodNameLength;
while (--i > leadingMatchingChars) {
if ((3&methodName2.charAt(i)) != (3&methodName.charAt(i))) { //these masks must match buildKey
return i;
}
}
throw new UnsupportedOperationException("Method names are too similar. Every annotated field must have a different field name.");
}
//TODO: change to map into small space to remove the hash table6
private static boolean namesBuildSameKey(String methodName2, String methodName, int c1, int c2, int c3, int cursor) {
return buildKey(methodName2, c1, c2, c3, cursor) == buildKey(methodName, c1, c2, c3, cursor);
}
//NOTE: if we need more than 128 methods can add c4 etc.
protected static int buildKey(PipeInvokeHandler handler, String value) {
//builds a value 7 bits long and no longer
return ((int)(15&value.length())<<6) | ((int)(3&value.charAt(handler.c1))<<4) | ((int)(3&value.charAt(handler.c2))<<2) | ((int)(3&value.charAt(handler.c3)));
}
private static int buildKey(String value, int c1, int c2, int c3, int cursor) {
switch (cursor) {
case 0:
return ((int)(15&value.length())<<6);
case 1:
return ((int)(15&value.length())<<6) | ((int)(3&value.charAt(c1))<<4);
case 2:
return ((int)(15&value.length())<<6) | ((int)(3&value.charAt(c1))<<4) | ((int)(3&value.charAt(c2))<<2);
default:
return ((int)(15&value.length())<<6) | ((int)(3&value.charAt(c1))<<4) | ((int)(3&value.charAt(c2))<<2) | ((int)(3&value.charAt(c3)));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy