All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.javanut.pronghorn.pipe.proxy.PipeInvokeHandler Maven / Gradle / Ivy

Go to download

Ring buffer based queuing utility for applications that require high performance and/or a small footprint. Well suited for embedded and stream based processing.

There is a newer version: 1.1.27
Show newest version
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