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

com.javanut.pronghorn.util.parse.JSONFieldMapping 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.util.parse;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.javanut.json.JSONAccumRule;
import com.javanut.json.JSONAligned;
import com.javanut.json.JSONRequired;
import com.javanut.json.JSONType;
import com.javanut.pronghorn.pipe.ChannelReader;
import com.javanut.pronghorn.pipe.util.hash.LongHashTable;
import com.javanut.pronghorn.util.Appendables;

import java.io.IOException;

public class JSONFieldMapping {
	
	private static final Logger logger = LoggerFactory.getLogger(JSONFieldMapping.class);
	
	private final JSONFieldSchema schema;
	private String name;
	private Object association;
	private Object validator;
	private JSONRequired isRequired;
	
	public final JSONType type;
	
	public JSONAccumRule accumRule;	
	public final boolean isAligned;
	private int[] values; //immutable once established
	private int dimensions; //immutable once established
	public String[] path; //immutable once established
	
	//capture first, last, all
	//align all values
	//
	
	
	public JSONFieldMapping(
					             JSONFieldSchema schema,
					             JSONType type,
					             JSONAligned isAligned) {
	
		//we need all the paths first in order 
		//to ensure that the multiplier works.
		this.schema = schema;
		this.type = type;
		this.isAligned = isAligned == JSONAligned.ALLIGNED;
		this.accumRule = null;//wait to set in setPath
	}

	public JSONFieldMapping(
					             JSONFieldSchema schema,
					             JSONType type,
					             JSONAligned isAligned,
					             JSONAccumRule accumRule) {
	
		//we need all the paths first in order 
		//to ensure that the multiplier works.
		this.schema = schema;
		this.type = type;
		this.isAligned = isAligned == JSONAligned.ALLIGNED;
		this.accumRule = accumRule; 
	}
	
	public String getName() {
		return name; //TODO: store as array of bytes...
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setAssociatedObject(Object optionalAssociation) {
		this.association = optionalAssociation;		
	}
	
	public Object getAssociatedObject() {
		return association;
	}
	
	public void setValidator(JSONRequired required, Object validator) {
		this.validator = validator;
		this.isRequired = required;
	}
	
	public JSONRequired isRequired() {
		return isRequired;
	}
	
	public Object getValidator() {
		return validator;
	}
	
	public void setPath(JSONFieldSchema schema, CharSequence ... path) {
		this.values = new int[path.length];
		int dimCounter = 0;
		for(int x = 0; x=0) {
				pathHash = prev + jsonFieldMapping.values[i];
				
			} else {
				//when value is less than 0 it is an array so the id,
				//must be moved up above the rest and the value is negative.
				pathHash = prev + (jsonFieldMapping.schema.uniqueFieldsCount()
						          -jsonFieldMapping.values[i]);
								
				int dimIdx;//lookup which fields make use of this array
				if (!LongHashTable.hasItem(lookupDimensions, pathHash)) {
					dimIdx = dimsIdx++;
					LongHashTable.setItem(lookupDimensions, pathHash, dimIdx);
				} else {
					dimIdx = LongHashTable.getItem(lookupDimensions, pathHash);
				}

				dimDepth++; //must increment before it is stored.
				
				//detect if this is the first addition and record the dim depth
				if (dimUsages[dimIdx][0]==0) {
					//first insert so record specific dim depth 
					addToList(dimIdx, dimDepth, dimUsages);	//adds count plus this field
					
					//logger.info("dim dimDepth {} {} len {}", dimIdx, dimDepth, dimUsages[dimIdx][0]);
				} else {
					assert(dimUsages[dimIdx][1] == dimDepth) : "Internal error, dim depth must match";
				}
				
				addToList(dimIdx, fieldIdx, dimUsages);
				//logger.info("dim fieldIdx {} {} {} ", dimIdx, fieldIdx, Arrays.toString(dimUsages[dimIdx]));
				
				//dimDepth++; moved above for testing remove this line
			}
		
		}
		
		if (LongHashTable.hasItem(lookupFieldTableLocal, pathHash)) {
			throw new UnsupportedOperationException("field "+fieldIdx+" conflicts with previous field, each must be unique.");
		}
		
//		if (jsonFieldMapping.groupId>=0) {
//			//record the pathHash and/or fieldIdx as part of the group
//		    //store the fieldIdx to be looked up from the groupId,
//			
//			//what is the row for this groupId??
//			//addToList(row, fieldIdx, target);
//		}
		
		LongHashTable.setItem(lookupFieldTableLocal, pathHash, fieldIdx);
		return dimsIdx;
	}

	//record all the fieldIDs which will are part of the same groupId.
	//record all the fieldIDs which make use of this same dimIdx
	private static void addToList(int rowIdx, int addValue, int[][] targetList) {
		int count = targetList[rowIdx][0];
		
		//not gc free but only done on startup 
		if (count+2 > targetList[rowIdx].length) {
			//must grow since we have no room for len plus old data plus 1
			
			int[] usages = new int[count+2];
			System.arraycopy(targetList[rowIdx], 0, usages, 0, count+1);		
			targetList[rowIdx] = usages;
			
		}
		
		targetList[rowIdx][0] = ++count;
		targetList[rowIdx][count] = addValue;
				
	}


	public  A dump(ChannelReader reader, A out) {
		
		switch (type) {
			case TypeBoolean:
				try {
						Appendables.appendValue(out, "Boolean recorded as: ", reader.readByte());
						out.append("\n");
				} catch (IOException ex) {
					throw new RuntimeException(ex);
				}	
				break;
			case TypeDecimal:
				try{
						long m = reader.readPackedLong();
						byte e = reader.readByte();
						
						out.append("Decimal recorded as: ");
						Appendables.appendDecimalValue(out, m, e);
						out.append("\n");
				} catch (IOException ex) {
					throw new RuntimeException(ex);
				}	
				break;
			case TypeInteger:
				try {
					Appendables.appendValue(out, "Integer recorded as: ", reader.readPackedLong());
					out.append("\n");
				} catch (IOException ex) {
					throw new RuntimeException(ex);
				}	
				break;
			case TypeString:
				try {
					int length = reader.readPackedInt();
					
					Appendables.appendValue(out, "String len: ",length);
					if (length>0) {
						out.append(" with body of ");
						reader.readUTFOfLength(length,out);
					}
					out.append("\n");
				} catch (IOException ex) {
					throw new RuntimeException(ex);
				}						   
				
				break;
			default:
				throw new UnsupportedOperationException();
		
		}
		
		return out;
	}

	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy