com.bazaarvoice.jolt.defaultr.Key Maven / Gradle / Ivy
/*
* Copyright 2013 Bazaarvoice, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bazaarvoice.jolt.defaultr;
import com.bazaarvoice.jolt.Defaultr;
import com.bazaarvoice.jolt.exception.TransformException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.bazaarvoice.jolt.defaultr.OPS.OR;
public abstract class Key {
/**
* Factory-ish method that recursively processes a Map into a Set objects.
*
* @param spec Simple Jackson default Map input
* @return Set of Keys from this level in the spec
*/
public static Set parseSpec( Map spec ) {
return processSpec( false, spec );
}
/**
* Recursively walk the spec input tree. Handle arrays by telling DefaultrKeys if they need to be ArrayKeys, and
* to find the max default array length.
*/
private static Set processSpec( boolean parentIsArray, Map spec ) {
// TODO switch to List and sort before returning
Set result = new HashSet<>();
for ( String key : spec.keySet() ) {
Object subSpec = spec.get( key );
if ( parentIsArray ) {
result.add( new ArrayKey( key, subSpec ) ); // this will recursively call processSpec if needed
}
else {
result.add( new MapKey( key, subSpec ) ); // this will recursively call processSpec if needed
}
}
return result;
}
private static final String OR_INPUT_REGEX = "\\" + Defaultr.WildCards.OR;
private static final Key.KeyPrecedenceComparator keyComparator = new Key.KeyPrecedenceComparator();
// Am I supposed to be parent of an array? If so I need to make sure that I inform
// my children they need to be ArrayKeys, and I need to make sure that the output array
// I will write to is big enough.
private boolean isArrayOutput = false;
private OPS op = null;
private int orCount = 0;
private int outputArraySize = -1;
protected Set children = null;
protected Object literalValue = null;
protected String rawKey;
protected List keyStrings;
public Key( String rawJsonKey, Object spec ) {
rawKey = rawJsonKey;
if ( rawJsonKey.endsWith( Defaultr.WildCards.ARRAY ) ) {
isArrayOutput = true;
rawKey = rawKey.replace( Defaultr.WildCards.ARRAY, "" );
}
op = OPS.parse( rawKey );
switch( op ){
case OR :
keyStrings = Arrays.asList( rawKey.split( Key.OR_INPUT_REGEX ) );
orCount = keyStrings.size();
break;
case LITERAL:
keyStrings = Arrays.asList( rawKey );
break;
case STAR:
keyStrings = Collections.emptyList();
break;
default :
throw new IllegalStateException( "Someone has added an op type without changing this method." );
}
// Spec is String -> Map or String -> Literal only
if ( spec instanceof Map ) {
children = processSpec( isArrayOutput(), (Map) spec );
if ( isArrayOutput() ) {
// loop over children and find the max literal value
for( Key childKey : children ) {
int childValue = childKey.getLiteralIntKey();
if ( childValue > outputArraySize ) {
outputArraySize = childValue;
}
}
}
}
else {
// literal such as String, number, or JSON array
literalValue = spec;
}
}
/**
* This is the main "recursive" method. The defaultee should never be null, because
* the defaultee wasn't null, it was null and we created it, OR there was
* a mismatch between the Defaultr Spec and the input, and we didn't recurse.
*/
public void applyChildren( Object defaultee ) {
if ( defaultee == null ) {
throw new TransformException( "Defaultee should never be null when " +
"passed to the applyChildren method." );
}
// This has nothing to do with this being an ArrayKey or MapKey, instead this is about
// this key being the parent of an Array in the output.
if ( isArrayOutput() && defaultee instanceof List) {
@SuppressWarnings( "unchecked" )
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy