Input: Create the proxy that does retries . Adds a strict error handler to the service . [CODESPLIT] public static MemcacheService createProxy ( final MemcacheService raw , final int retryCount ) { return ( MemcacheService ) java . lang . reflect . Proxy . newProxyInstance ( raw . getClass ( ) . getClassLoader ( ) , raw . getClass ( ) . getInterfaces ( ) , new MemcacheServiceRetryProxy ( raw , retryCount ) ) ; }


Input:
/ * ( non - Javadoc ) [CODESPLIT] @ Override public Object invoke ( Object proxy , Method meth , Object [ ] args ) throws Throwable { for ( int i = 0 ; i < this . tries ; i ++ ) { try { return meth . invoke ( this . raw , args ) ; } catch ( InvocationTargetException ex ) { if ( i == ( this . tries - 1 ) ) log . error ( "Memcache operation failed, giving up" , ex ) ; else log . warn ( "Error performing memcache operation, retrying: " + meth , ex ) ; } } // Will reach this point when we have exhausted our retries.
 return null ; }


Input: / * [CODESPLIT] @ Override public Translator < Object , Object > create ( final TypeKey < Object > tk , final CreateContext createCtx , final Path path ) { if ( tk . getTypeAsClass ( ) != Object . class ) return null ; return new NullSafeTranslator < Object , Object > ( ) { @ Override protected Object loadSafe ( final Value < Object > value , final LoadContext ctx , final Path path ) throws SkipException { return value . get ( ) ; } @ Override protected Value < Object > saveSafe ( final Object pojo , final boolean index , final SaveContext saveCtx , final Path path ) throws SkipException { final TypeKey < Object > runtimeTypeKey = new TypeKey <> ( pojo . getClass ( ) ) ; // We really only need the createctx so that the translators can get a factory. final Translator < Object , Object > realTranslator = translators . get ( runtimeTypeKey , createCtx , path ) ; return realTranslator . save ( pojo , index , saveCtx , path ) ; } } ; }


Input:
Iterate through all pending futures and get () them forcing any callbacks to be called . This is used only by the AsyncCacheFilter ( if using cache without Objectify ) or ObjectifyFilter ( if using Objectify normally ) because we don t have a proper hook otherwise . [CODESPLIT] public static void completeAllPendingFutures ( ) { // This will cause done Futures to fire callbacks and remove themselves
 for ( Future < ? > fut : pending . get ( ) . keySet ( ) ) { try { fut . get ( ) ; } catch ( Exception e ) { log . error ( "Error cleaning up pending Future: " + fut , e ) ; } } }


Input:
<p > All @Entity and @Subclass classes ( for both entity and embedded classes ) must be registered before using Objectify to load or save data . This method must be called in a single - threaded mode sometime around application initialization . < / p > [CODESPLIT] public < T > void register ( Class < T > clazz ) { // There are two possible cases
 // 1) This might be a simple class with @Entity
 // 2) This might be a class annotated with @Subclass
 // @Entity is inherited, but we only create entity metadata for the class with the @Entity declaration
 if ( TypeUtils . isDeclaredAnnotationPresent ( clazz , Entity . class ) ) { String kind = Key . getKind ( clazz ) ; // If we are already registered, ignore
 if ( this . byKind . containsKey ( kind ) ) return ; EntityMetadata < T > cmeta = new EntityMetadata <> ( this . fact , clazz ) ; this . byKind . put ( kind , cmeta ) ; if ( cmeta . getCacheExpirySeconds ( ) != null ) this . cacheEnabled = true ; } else if ( clazz . isAnnotationPresent ( Subclass . class ) ) { // We just need to make sure that a translator was created
 fact . getTranslators ( ) . getRoot ( clazz ) ; } else { throw new IllegalArgumentException ( clazz + " must be annotated with either @Entity or @Subclass" ) ; } }


Input: Gets metadata for the specified kind [CODESPLIT] public < T > EntityMetadata < T > getMetadataSafe ( String kind ) throws IllegalArgumentException { EntityMetadata < T > metadata = this . getMetadata ( kind ) ; if ( metadata == null ) throw new IllegalArgumentException ( "No entity class has been registered which matches kind '" + kind + "'" ) ; else return metadata ; }


Input: Perform a keys - only query . [CODESPLIT] public < T > QueryResults < Key < T > > queryKeysOnly ( final KeyQuery query ) { log . trace ( "Starting keys-only query" ) ; return new KeyQueryResults <> ( ds . run ( query ) ) ; }


Input: Perform a keys - only plus batch gets . [CODESPLIT] public < T > QueryResults < T > queryHybrid ( final KeyQuery query , final int chunkSize ) { log . trace ( "Starting hybrid query" ) ; final QueryResults < Key < T > > results = new KeyQueryResults <> ( ds . run ( query ) ) ; return new HybridQueryResults <> ( loader . createLoadEngine ( ) , results , chunkSize ) ; }


Input:
A normal non - hybrid query [CODESPLIT] public < T > QueryResults < T > queryNormal ( final EntityQuery query , final int chunkSize ) { log . trace ( "Starting normal query" ) ; // Normal queries are actually more complex than hybrid queries because we need the fetched entities to
 // be stuffed back into the engine to satisfy @Load instructions without extra fetching. Even though
 // this looks like we're doing hybrid load-by-key operations, the data is pulled from the stuffed values.
 final LoadEngine loadEngine = loader . createLoadEngine ( ) ; final QueryResults < Entity > entityResults = ds . run ( query ) ; final QueryResults < com . google . cloud . datastore . Key > stuffed = new StuffingQueryResults ( loadEngine , entityResults ) ; final QueryResults < Key < T > > keyResults = new KeyQueryResults <> ( stuffed ) ; return new HybridQueryResults <> ( loadEngine , keyResults , chunkSize ) ; }


Input: A projection query . Bypasses the session entirely . [CODESPLIT] public < T > QueryResults < T > queryProjection ( final ProjectionEntityQuery query ) { log . trace ( "Starting projection query" ) ; final LoadEngine loadEngine = loader . createLoadEngine ( ) ; return new ProjectionQueryResults <> ( ds . run ( query ) , loadEngine ) ; }


Input: The fundamental query count operation . This doesn t appear to be implemented in the new SDK so we simulate with a keys - only query . [CODESPLIT] public int queryCount ( final KeyQuery query ) { log . trace ( "Starting count query" ) ; final QueryResults < com . google . cloud . datastore . Key > results = ds . run ( query ) ; return Iterators . size ( results ) ; }


Input: Detects Integer . MAX_VALUE and prevents OOM exceptions [CODESPLIT] private < T > Iterator < Iterator < T > > safePartition ( final Iterator < T > input , int chunkSize ) { // Cloud Datastore library errors if you try to fetch more than 1000 keys at a time if ( chunkSize > 1000 ) { chunkSize = 1000 ; } return Iterators . transform ( Iterators . partition ( input , chunkSize ) , IterateFunction . instance ( ) ) ; }


Input: Loads them ; note that it s possible for some loaded results to be null [CODESPLIT] private Iterator < ResultWithCursor < T > > load ( final Iterator < ResultWithCursor < Key < T > > > keys ) { final List < Entry < ResultWithCursor < Key < T > > , Result < T > > > results = Lists . newArrayList ( ) ; while ( keys . hasNext ( ) ) { final ResultWithCursor < Key < T > > next = keys . next ( ) ; results . add ( Maps . immutableEntry ( next , loadEngine . load ( next . getResult ( ) ) ) ) ; } loadEngine . execute ( ) ; return Iterators . transform ( results . iterator ( ) , entry -> new ResultWithCursor <> ( entry . getValue ( ) . now ( ) , entry . getKey ( ) . getCursorAfter ( ) ) ) ; }


Input: Copies an array of primitive longs while boxing them at the same time and then converting into a list . Can t use { @link Arrays#asList ( Object [] ) } directly as that will create a list of arrays instead . [CODESPLIT] public static List < Long > asList ( long ... elements ) { Objects . requireNonNull ( elements ) ; Long [ ] copy = new Long [ elements . length ] ; for ( int index = 0 ; index < elements . length ; index ++ ) { copy [ index ] = elements [ index ] ; } return Arrays . asList ( copy ) ; }


Input: Like now () but throws NotFoundException instead of returning null . [CODESPLIT] public final T safe ( ) throws NotFoundException { T t = now ( ) ; if ( t == null ) throw new NotFoundException ( key ) ; else return t ; }


Input: Create a log a message for a given path [CODESPLIT] public static String msg ( Path path , String msg ) { StringBuilder bld = new StringBuilder ( ) ; bld . append ( "\t." ) ; bld . append ( path . toPathString ( ) ) ; if ( bld . length ( ) < PATH_PADDING ) while ( bld . length ( ) < PATH_PADDING ) bld . append ( ' ' ) ; else bld . append ( ' ' ) ; bld . append ( msg ) ; return bld . toString ( ) ; }


Input: Key . create ( key ) is easier to type than new Key<Blah > ( key ) [CODESPLIT] public static < T > Key < T > create ( final com . google . cloud . datastore . Key raw ) { if ( raw == null ) throw new NullPointerException ( "Cannot create a Key<?> from a null datastore Key" ) ; return new Key <> ( raw ) ; }


Input: Key . create ( Blah . class id ) is easier to type than new Key<Blah > ( Blah . class id ) [CODESPLIT] public static < T > Key < T > create ( final Class < ? extends T > kindClass , final long id ) { return new Key <> ( kindClass , id ) ; }


Input: Key . create ( Blah . class name ) is easier to type than new Key<Blah > ( Blah . class name ) [CODESPLIT] public static < T > Key < T > create ( final Class < ? extends T > kindClass , final String name ) { return new Key <> ( kindClass , name ) ; }


Input: Key . create ( urlSafeString ) is easier to type than new Key<Blah > ( urlSafeString ) [CODESPLIT] public static < T > Key < T > create ( final String urlSafeString ) { if ( urlSafeString == null ) throw new NullPointerException ( "Cannot create a Key<?> from a null String" ) ; return new Key <> ( urlSafeString ) ; }


Input: Create a key from a registered POJO entity . [CODESPLIT] public static < T > Key < T > create ( final T pojo ) { return ObjectifyService . factory ( ) . keys ( ) . keyOf ( pojo ) ; }


Input:
<p > The new cloud sdk Key doesn t have compareTo () so we reimplement the logic from the old GAE SDK . < / p > [CODESPLIT] @ Override public int compareTo ( final Key < ? > other ) { if ( this . raw == other . raw ) { return 0 ; } { final int result = this . raw . getProjectId ( ) . compareTo ( other . raw . getProjectId ( ) ) ; if ( result != 0 ) return result ; } { final int result = this . raw . getNamespace ( ) . compareTo ( other . raw . getNamespace ( ) ) ; if ( result != 0 ) return result ; } { final int result = this . compareAncestors ( other ) ; if ( result != 0 ) return result ; } { // Too bad PathElement and Key don't share any kind of interface grrr
 final int result = this . getRaw ( ) . getKind ( ) . compareTo ( other . getRaw ( ) . getKind ( ) ) ; if ( result != 0 ) { return result ; } else if ( this . raw . getNameOrId ( ) == null && other . raw . getNameOrId ( ) == null ) { return compareToWithIdentityHash ( this . raw , other . raw ) ; } else if ( this . raw . hasId ( ) ) { return other . raw . hasId ( ) ? Long . compare ( this . raw . getId ( ) , other . raw . getId ( ) ) : - 1 ; } else { return other . raw . hasId ( ) ? 1 : this . raw . getName ( ) . compareTo ( other . raw . getName ( ) ) ; } } }


Input: I have no idea what this is about it was in the old logic [CODESPLIT] private int compareToWithIdentityHash ( final Object k1 , final Object k2 ) { return Integer . compare ( System . identityHashCode ( k1 ) , System . identityHashCode ( k2 ) ) ; }


Input: Easy null - safe conversion of the raw key . [CODESPLIT] public static < V > Key < V > key ( final com . google . cloud . datastore . Key raw ) { if ( raw == null ) return null ; else return new Key <> ( raw ) ; }


Input: Easy null - safe conversion of the typed key . [CODESPLIT] public static com . google . cloud . datastore . Key key ( final Key < ? > typed ) { if ( typed == null ) return null ; else return typed . getRaw ( ) ; }


Input: <p > Determines the kind for a Class as understood by the datastore . The first class in a hierarchy that has @Entity defines the kind ( either explicitly or as that class simplename ) . < / p > [CODESPLIT] public static String getKind ( final Class < ? > clazz ) { final String kind = getKindRecursive ( clazz ) ; if ( kind == null ) return clazz . getSimpleName ( ) ; else return kind ; }


Input: <p > Recursively looks for the @Entity annotation . < / p > [CODESPLIT] private static String getKindRecursive ( final Class < ? > clazz ) { if ( clazz == Object . class ) return null ; final String kind = getKindHere ( clazz ) ; if ( kind != null ) return kind ; else return getKindRecursive ( clazz . getSuperclass ( ) ) ; }


Input:
Get the kind from the class if the class has an [CODESPLIT] private static String getKindHere ( final Class < ? > clazz ) { // @Entity is inherited so we have to be explicit about the declared annotations
 final Entity ourAnn = TypeUtils . getDeclaredAnnotation ( clazz , Entity . class ) ; if ( ourAnn != null ) if ( ourAnn . name ( ) . length ( ) != 0 ) return ourAnn . name ( ) ; else return clazz . getSimpleName ( ) ; return null ; }


Input: Checks if the given type is a class that is supposed to have type parameters but doesn t . In other words if it s a really raw type . [CODESPLIT] static boolean isMissingTypeParameters ( Type type ) { if ( type instanceof Class ) { for ( Class < ? > clazz = ( Class < ? > ) type ; clazz != null ; clazz = clazz . getEnclosingClass ( ) ) { if ( clazz . getTypeParameters ( ) . length != 0 ) return true ; } return false ; } else if ( type instanceof ParameterizedType ) { return false ; } else { throw new AssertionError ( "Unexpected type " + type . getClass ( ) ) ; } }


Input: Checks if the capture of subType is a subtype of superType [CODESPLIT] public static boolean isSuperType ( Type superType , Type subType ) { if ( superType instanceof ParameterizedType || superType instanceof Class || superType instanceof GenericArrayType ) { Class < ? > superClass = erase ( superType ) ; Type mappedSubType = getExactSuperType ( capture ( subType ) , superClass ) ; if ( mappedSubType == null ) { return false ; } else if ( superType instanceof Class < ? > ) { return true ; } else if ( mappedSubType instanceof Class < ? > ) { // TODO treat supertype by being raw type differently ("supertype, but with warnings") return true ; // class has no parameters, or it's a raw type } else if ( mappedSubType instanceof GenericArrayType ) { Type superComponentType = getArrayComponentType ( superType ) ; assert superComponentType != null ; Type mappedSubComponentType = getArrayComponentType ( mappedSubType ) ; assert mappedSubComponentType != null ; return isSuperType ( superComponentType , mappedSubComponentType ) ; } else { assert mappedSubType instanceof ParameterizedType ; ParameterizedType pMappedSubType = ( ParameterizedType ) mappedSubType ; assert pMappedSubType . getRawType ( ) == superClass ; ParameterizedType pSuperType = ( ParameterizedType ) superType ; Type [ ] superTypeArgs = pSuperType . getActualTypeArguments ( ) ; Type [ ] subTypeArgs = pMappedSubType . getActualTypeArguments ( ) ; assert superTypeArgs . length == subTypeArgs . length ; for ( int i = 0 ; i < superTypeArgs . length ; i ++ ) { if ( ! contains ( superTypeArgs [ i ] , subTypeArgs [ i ] ) ) { return false ; } } // params of the class itself match, so if the owner types are supertypes too, it's a supertype. return pSuperType . getOwnerType ( ) == null || isSuperType ( pSuperType . getOwnerType ( ) , pMappedSubType . getOwnerType ( ) ) ; } } else if ( superType instanceof CaptureType ) { if ( superType . equals ( subType ) ) return true ; for ( Type lowerBound : ( ( CaptureType ) superType ) . getLowerBounds ( ) ) { if ( isSuperType ( lowerBound , subType ) ) { return true ; } } return false ; } else if ( superType instanceof GenericArrayType ) { return isArraySupertype ( superType , subType ) ; } else { throw new RuntimeException ( "not implemented: " + superType . getClass ( ) ) ; } }


Input: Returns the direct supertypes of the given type . Resolves type parameters . [CODESPLIT] private static Type [ ] getExactDirectSuperTypes ( Type type ) { if ( type instanceof ParameterizedType || type instanceof Class ) { Class < ? > clazz ; if ( type instanceof ParameterizedType ) { clazz = ( Class < ? > ) ( ( ParameterizedType ) type ) . getRawType ( ) ; } else { // TODO primitive types? clazz = ( Class < ? > ) type ; if ( clazz . isArray ( ) ) return getArrayExactDirectSuperTypes ( clazz ) ; } Type [ ] superInterfaces = clazz . getGenericInterfaces ( ) ; Type superClass = clazz . getGenericSuperclass ( ) ; // the only supertype of an interface without superinterfaces is Object if ( superClass == null && superInterfaces . length == 0 && clazz . isInterface ( ) ) { return new Type [ ] { Object . class } ; } Type [ ] result ; int resultIndex ; if ( superClass == null ) { result = new Type [ superInterfaces . length ] ; resultIndex = 0 ; } else { result = new Type [ superInterfaces . length + 1 ] ; resultIndex = 1 ; result [ 0 ] = mapTypeParameters ( superClass , type ) ; } for ( Type superInterface : superInterfaces ) { result [ resultIndex ++ ] = mapTypeParameters ( superInterface , type ) ; } return result ; } else if ( type instanceof TypeVariable ) { TypeVariable < ? > tv = ( TypeVariable < ? > ) type ; return tv . getBounds ( ) ; } else if ( type instanceof WildcardType ) { // This should be a rare case: normally this wildcard is already captured. // But it does happen if the upper bound of a type variable contains a wildcard // TODO shouldn't upper bound of type variable have been captured too? (making this case impossible?) return ( ( WildcardType ) type ) . getUpperBounds ( ) ; } else if ( type instanceof CaptureType ) { return ( ( CaptureType ) type ) . getUpperBounds ( ) ; } else if ( type instanceof GenericArrayType ) { return getArrayExactDirectSuperTypes ( type ) ; } else if ( type == null ) { throw new NullPointerException ( ) ; } else { throw new RuntimeException ( "not implemented type: " + type ) ; } }


Input: Returns the exact type of the given field in the given type . This may be different from <tt > f . getGenericType () < / tt > when the field was declared in a superclass or <tt > type< / tt > has a type parameter that is used in the type of the field or <tt > type< / tt > is a raw type . [CODESPLIT] public static Type getExactFieldType ( Field f , Type type ) { Type returnType = f . getGenericType ( ) ; Type exactDeclaringType = getExactSuperType ( capture ( type ) , f . getDeclaringClass ( ) ) ; if ( exactDeclaringType == null ) { // capture(type) is not a subtype of f.getDeclaringClass() throw new IllegalArgumentException ( "The field " + f + " is not a member of type " + type ) ; } return mapTypeParameters ( returnType , exactDeclaringType ) ; }


Input: Applies capture conversion to the given type . [CODESPLIT] public static Type capture ( Type type ) { if ( type instanceof ParameterizedType ) { return capture ( ( ParameterizedType ) type ) ; } else { return type ; } }


Input: Get the relevant translator creating it if necessary . [CODESPLIT] public < P , D > Translator < P , D > getTranslator ( final TypeKey < P > tk , final CreateContext ctx , final Path path ) { return factory . getTranslators ( ) . get ( tk , ctx , path ) ; }


Input: Get the populator for the specified class . This requires looking up the translator for that class and then getting the populator from it . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < P > Populator < P > getPopulator ( final Class < P > clazz , final Path path ) { if ( clazz == null || clazz . equals ( Object . class ) ) { return ( Populator < P > ) NullPopulator . INSTANCE ; } else { final ClassTranslator < P > classTranslator = ( ClassTranslator < P > ) this . < P , FullEntity < ? > > getTranslator ( new TypeKey <> ( clazz ) , this , path ) ; return classTranslator . getPopulator ( ) ; } }


Input: / * [CODESPLIT] @ Override public void load ( FullEntity < ? > node , LoadContext ctx , Path path , final P into ) { superPopulator . load ( node , ctx , path , into ) ; ctx . enterContainerContext ( into ) ; try { for ( final Populator < Object > prop : props ) { prop . load ( node , ctx , path , into ) ; } } finally { ctx . exitContainerContext ( into ) ; } // If there are any @OnLoad methods, call them after everything else if ( ! onLoadMethods . isEmpty ( ) ) { ctx . defer ( new Runnable ( ) { @ Override public void run ( ) { for ( LifecycleMethod method : onLoadMethods ) method . execute ( into ) ; } @ Override public String toString ( ) { return "(deferred invoke " + clazz + " @OnLoad callbacks on " + into + ")" ; } } ) ; } }


Input: / * [CODESPLIT] @ Override public void save ( P pojo , boolean index , SaveContext ctx , Path path , FullEntity . Builder < ? > into ) { superPopulator . save ( pojo , index , ctx , path , into ) ; // Must do @OnSave methods after superclass but before actual population if ( ! ctx . skipLifecycle ( ) && ! onSaveMethods . isEmpty ( ) ) for ( LifecycleMethod method : onSaveMethods ) method . execute ( pojo ) ; if ( indexInstruction != null ) index = indexInstruction ; for ( final Populator < Object > prop : props ) { prop . save ( pojo , index , ctx , path , into ) ; } }


Input: Figure out if there is an index instruction for the whole class . [CODESPLIT] private Boolean getIndexInstruction ( Class < P > clazz ) { Index ind = clazz . getAnnotation ( Index . class ) ; Unindex unind = clazz . getAnnotation ( Unindex . class ) ; if ( ind != null && unind != null ) throw new IllegalStateException ( "You cannot have @Index and @Unindex on the same class: " + clazz ) ; if ( ind != null ) return true ; else if ( unind != null ) return false ; else return null ; }


Input: Determine if we should create a Property for the field . Things we ignore : static final [CODESPLIT] private boolean isOfInterest ( Field field ) { return ! field . isAnnotationPresent ( Ignore . class ) && ( ( field . getModifiers ( ) & NOT_SAVEABLE_MODIFIERS ) == 0 ) && ! field . isSynthetic ( ) && ! field . getName ( ) . startsWith ( "bitmap$init" ) ; // Scala adds a field bitmap$init$0 and bitmap$init$1 etc }


Input: Determine if we should create a Property for the method ( ie [CODESPLIT] private boolean isOfInterest ( Method method ) { for ( Annotation [ ] annos : method . getParameterAnnotations ( ) ) if ( TypeUtils . getAnnotation ( annos , AlsoLoad . class ) != null ) return true ; return false ; }


Input: Get all the persistable fields and methods declared on a class . Ignores superclasses . [CODESPLIT] private List < Property > getDeclaredProperties ( ObjectifyFactory fact , Class < ? > clazz ) { List < Property > good = new ArrayList <> ( ) ; for ( Field field : clazz . getDeclaredFields ( ) ) if ( isOfInterest ( field ) ) good . add ( new FieldProperty ( fact , clazz , field ) ) ; for ( Method method : clazz . getDeclaredMethods ( ) ) if ( isOfInterest ( method ) ) good . add ( new MethodProperty ( method ) ) ; return good ; }


Input: Gets the key metadata but only if this was an [CODESPLIT] public KeyMetadata < P > getKeyMetadata ( ) { final Populator < Object > populator = props . get ( 0 ) ; Preconditions . checkState ( populator instanceof KeyPopulator , "Cannot get KeyMetadata for non-@Entity class " + this . clazz ) ; return ( ( KeyPopulator < P > ) populator ) . getKeyMetadata ( ) ; }


Input: Gets a result using the session cache if possible . [CODESPLIT] public < T > Result < T > get ( final Key < T > key ) { assert ! isExecuted ( ) ; SessionValue < T > sv = getSession ( ) . get ( key ) ; if ( sv == null ) { log . trace ( "Adding to round (session miss): {}" , key ) ; this . pending . add ( key . getRaw ( ) ) ; Result < T > result = new ResultCache < T > ( ) { @ Override @ SuppressWarnings ( "unchecked" ) public T nowUncached ( ) { // Because clients could conceivably get() in the middle of our operations (see LoadCollectionRefsTest.specialListWorks()), // we need to check for early execution. This will perform poorly, but at least it will work. //assert Round.this.isExecuted(); loadEngine . execute ( ) ; return ( T ) translated . now ( ) . get ( key ) ; } @ Override public String toString ( ) { return "(Fetch result for " + key + ")" ; } } ; sv = new SessionValue <> ( result , getLoadArrangement ( ) ) ; getSession ( ) . add ( key , sv ) ; } else { log . trace ( "Adding to round (session hit): {}" , key ) ; if ( sv . loadWith ( getLoadArrangement ( ) ) ) { log . trace ( "New load group arrangement, checking for upgrades: {}" , getLoadArrangement ( ) ) ; // We are looking at a brand-new arrangement for something that already existed in the session. // We need to go through any Ref<?>s that might be in need of loading. We find those refs by // actually saving the entity into a custom SaveContext. T thing = sv . getResult ( ) . now ( ) ; if ( thing != null ) { SaveContext saveCtx = new SaveContext ( ) { @ Override public boolean skipLifecycle ( ) { return true ; } @ Override public com . google . cloud . datastore . Key saveRef ( Ref < ? > value , LoadConditions loadConditions ) { com . google . cloud . datastore . Key key = super . saveRef ( value , loadConditions ) ; if ( loadEngine . shouldLoad ( loadConditions ) ) { log . trace ( "Upgrading key {}" , key ) ; loadEngine . load ( value . key ( ) ) ; } return key ; } } ; // We throw away the saved entity and we are done loadEngine . ofy . factory ( ) . getMetadataForEntity ( thing ) . save ( thing , saveCtx ) ; } } } return sv . getResult ( ) ; }


Input: Turn this into a result set [CODESPLIT] public void execute ( ) { if ( needsExecution ( ) ) { log . trace ( "Executing round: {}" , pending ) ; Result < Map < com . google . cloud . datastore . Key , Entity > > fetched = fetchPending ( ) ; translated = loadEngine . translate ( fetched ) ; // If we're in a transaction (and beyond the first round), force all subsequent rounds to complete. // This effectively means that only the first round can be asynchronous; all other rounds are // materialized immediately. The reason for this is that there are some nasty edge cases with @Load // annotations in transactions getting called after the transaction closes. This is possibly not the // best solution to the problem, but it solves the problem now. if ( loadEngine . ofy . getTransaction ( ) != null && depth > 0 ) translated . now ( ) ; } }


Input: Possibly pulls some values from the stuffed collection [CODESPLIT] private Result < Map < com . google . cloud . datastore . Key , Entity > > fetchPending ( ) { // We don't need to fetch anything that has been stuffed final Map < com . google . cloud . datastore . Key , Entity > combined = new HashMap <> ( ) ; Set < com . google . cloud . datastore . Key > fetch = new HashSet <> ( ) ; for ( com . google . cloud . datastore . Key key : pending ) { Entity ent = stuffed . get ( key ) ; if ( ent == null ) fetch . add ( key ) ; else combined . put ( key , ent ) ; } if ( fetch . isEmpty ( ) ) { return new ResultNow <> ( combined ) ; } else { final Result < Map < com . google . cloud . datastore . Key , Entity > > fetched = loadEngine . fetch ( fetch ) ; return ( ) -> { combined . putAll ( fetched . now ( ) ) ; return combined ; } ; } }


Input: / * [CODESPLIT] @ Override public P loadSafe ( final Value < FullEntity < ? > > container , final LoadContext ctx , final Path path ) throws SkipException { // check if we need to redirect to a different translator final String containerDiscriminator = container . get ( ) . contains ( DISCRIMINATOR_PROPERTY ) ? container . get ( ) . getString ( DISCRIMINATOR_PROPERTY ) : null ; // wow no Optional or nullable get if ( ! Objects . equals ( discriminator , containerDiscriminator ) ) { final ClassTranslator < ? extends P > translator = byDiscriminator . get ( containerDiscriminator ) ; if ( translator == null ) { throw new IllegalStateException ( "Datastore object has discriminator value '" + containerDiscriminator + "' but no relevant @Subclass is registered" ) ; } else { // This fixes alsoLoad names in discriminators by changing the discriminator to what the // translator expects for loading that subclass. Otherwise we'll get the error above since the // translator discriminator and the container discriminator won't match. final StringValue discriminatorValue = StringValue . newBuilder ( translator . getDiscriminator ( ) ) . setExcludeFromIndexes ( true ) . build ( ) ; final FullEntity < ? > updatedEntity = FullEntity . newBuilder ( container . get ( ) ) . set ( DISCRIMINATOR_PROPERTY , discriminatorValue ) . build ( ) ; return translator . load ( EntityValue . of ( updatedEntity ) , ctx , path ) ; } } else { // This is a normal load if ( log . isTraceEnabled ( ) ) log . trace ( LogUtils . msg ( path , "Instantiating a " + declaredClass . getName ( ) ) ) ; final P into = forge . construct ( declaredClass ) ; populator . load ( container . get ( ) , ctx , path , into ) ; return into ; } }


Input: / * [CODESPLIT] @ Override public Value < FullEntity < ? > > saveSafe ( final P pojo , final boolean index , final SaveContext ctx , final Path path ) throws SkipException { // check if we need to redirect to a different translator if ( pojo . getClass ( ) != declaredClass ) { // Sometimes generics are more of a hindrance than a help @ SuppressWarnings ( "unchecked" ) final ClassTranslator < P > translator = ( ClassTranslator < P > ) byClass . get ( pojo . getClass ( ) ) ; if ( translator == null ) throw new IllegalStateException ( "Class '" + pojo . getClass ( ) + "' is not a registered @Subclass" ) ; else return translator . save ( pojo , index , ctx , path ) ; } else { // This is a normal save final FullEntity . Builder < IncompleteKey > into = FullEntity . newBuilder ( ) ; populator . save ( pojo , index , ctx , path , into ) ; if ( discriminator != null ) { into . set ( DISCRIMINATOR_PROPERTY , StringValue . newBuilder ( discriminator ) . setExcludeFromIndexes ( true ) . build ( ) ) ; if ( ! indexedDiscriminators . isEmpty ( ) ) into . set ( DISCRIMINATOR_INDEX_PROPERTY , ListValue . of ( indexedDiscriminators ) ) ; } // The question of whether to index this is weird. In order for subthings to be indexed, the entity needs // to be indexed. But then lists with index-heterogeous values (say, nulls) get reordered (!) // by the datastore. So we always index EntityValues and force all the list translators homogenize their lists. // Gross but seems to be the only way. return EntityValue . of ( into . build ( ) ) ; } }


Input: Recursively go through the class hierarchy adding any discriminators that are indexed [CODESPLIT] private void addIndexedDiscriminators ( final Class < ? > clazz ) { if ( clazz == Object . class ) return ; this . addIndexedDiscriminators ( clazz . getSuperclass ( ) ) ; final Subclass sub = clazz . getAnnotation ( Subclass . class ) ; if ( sub != null && sub . index ( ) ) { final String disc = ( sub . name ( ) . length ( ) > 0 ) ? sub . name ( ) : clazz . getSimpleName ( ) ; this . indexedDiscriminators . add ( StringValue . of ( disc ) ) ; } }


Input: Register a subclass translator with this class translator . That way if we get called upon to translate an instance of the subclass we will forward to the correct translator . [CODESPLIT] public void registerSubclass ( ClassTranslator < ? extends P > translator ) { byDiscriminator . put ( translator . getDiscriminator ( ) , translator ) ; Subclass sub = translator . getDeclaredClass ( ) . getAnnotation ( Subclass . class ) ; for ( String alsoLoad : sub . alsoLoad ( ) ) byDiscriminator . put ( alsoLoad , translator ) ; byClass . put ( translator . getDeclaredClass ( ) , translator ) ; }


Input: Get the component type of a Collection . [CODESPLIT] public static Type getCollectionComponentType ( Type collectionType ) { Type componentType = GenericTypeReflector . getTypeParameter ( collectionType , Collection . class . getTypeParameters ( ) [ 0 ] ) ; if ( componentType == null ) // if it was a raw type, just assume Object return Object . class ; else return componentType ; }


Input: Get the key type of a Map . [CODESPLIT] public static Type getMapKeyType ( Type mapType ) { Type componentType = GenericTypeReflector . getTypeParameter ( mapType , Map . class . getTypeParameters ( ) [ 0 ] ) ; if ( componentType == null ) // if it was a raw type, just assume Object return Object . class ; else return componentType ; }


Input: Recursive method which reverses the path into a ForwardPath . [CODESPLIT] public static ForwardPath of ( Path path ) { ForwardPath next = new ForwardPath ( path ) ; if ( path . getPrevious ( ) == Path . root ( ) ) return next ; ForwardPath previous = of ( path . getPrevious ( ) ) ; previous . next = next ; return previous ; }


Input: Get the complete path in this chain typically for error messages or debugging [CODESPLIT] public Path getFinalPath ( ) { ForwardPath here = this ; while ( here . next != null ) here = here . next ; return here . getPath ( ) ; }


Input: Create the full x . y . z string [CODESPLIT] public String toPathString ( ) { if ( this == ROOT ) { return "" ; } else { StringBuilder builder = new StringBuilder ( ) ; toPathString ( builder ) ; return builder . toString ( ) ; } }


Input: ROOT is 0 top level Entity properties are 1 embedded things are higher . [CODESPLIT] public int depth ( ) { int depth = 0 ; Path here = this ; while ( here != ROOT ) { depth ++ ; here = here . previous ; } return depth ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < E > Result < Key < E > > entity ( final E entity ) { final Result < Map < Key < E > , E > > base = this . < E > entities ( Collections . singleton ( entity ) ) ; return new ResultWrapper < Map < Key < E > , E > , Key < E > > ( base ) { private static final long serialVersionUID = 1L ; @ Override protected Key < E > wrap ( final Map < Key < E > , E > base ) { return base . keySet ( ) . iterator ( ) . next ( ) ; } } ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < E > Result < Map < Key < E > , E > > entities ( final E ... entities ) { return this . entities ( Arrays . asList ( entities ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < E > Result < Map < Key < E > , E > > entities ( final Iterable < E > entities ) { return ofy . createWriteEngine ( ) . save ( entities ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public FullEntity < ? > toEntity ( final Object pojo ) { if ( pojo instanceof FullEntity < ? > ) { return ( FullEntity < ? > ) pojo ; } else { @ SuppressWarnings ( "unchecked" ) final EntityMetadata < Object > meta = ( EntityMetadata < Object > ) ofy . factory ( ) . getMetadata ( pojo . getClass ( ) ) ; return meta . save ( pojo , new SaveContext ( ) ) ; } }


Input:
<p > Gets the Buckets for the specified keys . A bucket is built around an IdentifiableValue so you can putAll () them without the risk of overwriting other threads changes . Buckets also hide the underlying details of storage for negative empty and uncacheable results . < / p > [CODESPLIT] public Map < Key , Bucket > getAll ( final Iterable < Key > keys ) { final Map < Key , Bucket > result = new HashMap <> ( ) ; // Sort out the ones that are uncacheable
 final Set < Key > potentials = new HashSet <> ( ) ; for ( final Key key : keys ) { if ( ! cacheControl . isCacheable ( key ) ) result . put ( key , new Bucket ( key ) ) ; else potentials . add ( key ) ; } Map < Key , IdentifiableValue > casValues ; try { casValues = this . memcache . getIdentifiables ( potentials ) ; } catch ( Exception ex ) { // This should really only be a problem if the serialization format for an Entity changes,
 // or someone put a badly-serializing object in the cache underneath us.
 log . warn ( "Error obtaining cache for " + potentials , ex ) ; casValues = new HashMap <> ( ) ; } // Now create the remaining buckets
 for ( final Key key : keys ) { final IdentifiableValue casValue = casValues . get ( key ) ; // Might be null, which means uncacheable
 final Bucket buck = new Bucket ( key , casValue ) ; result . put ( key , buck ) ; if ( buck . isEmpty ( ) ) this . stats . recordMiss ( buck . getKey ( ) ) ; else this . stats . recordHit ( buck . getKey ( ) ) ; } return result ; }


Input:
Update a set of buckets with new values . If collisions occur resets the memcache value to null . [CODESPLIT] public void putAll ( final Collection < Bucket > updates ) { final Set < Key > good = this . cachePutIfUntouched ( updates ) ; if ( good . size ( ) == updates . size ( ) ) return ; // Figure out which ones were bad
 final List < Key > bad = updates . stream ( ) . map ( Bucket :: getKey ) . filter ( key -> ! good . contains ( key ) ) . collect ( Collectors . toList ( ) ) ; if ( ! bad . isEmpty ( ) ) { // So we had some collisions.  We need to reset these back to null, but do it in a safe way - if we
 // blindly set null something already null, it will break any putIfUntouched() which saw the first null.
 // This could result in write contention starving out a real write.  The solution is to only reset things
 // that are not already null.
 final Map < Key , Object > cached = this . cacheGetAll ( bad ) ; // Remove the stuff we don't care about
 cached . values ( ) . removeIf ( Objects :: isNull ) ; this . empty ( cached . keySet ( ) ) ; } }


Input: Revert a set of keys to the empty state . Will loop on this several times just in case the memcache write fails - we don t want to leave the cache in a nasty state . [CODESPLIT] public void empty ( final Iterable < Key > keys ) { final Map < Key , Object > updates = new HashMap <> ( ) ; for ( final Key key : keys ) if ( cacheControl . isCacheable ( key ) ) updates . put ( key , null ) ; this . memcacheWithRetry . putAll ( updates ) ; }


Input: Put buckets in the cache checking for cacheability and collisions . [CODESPLIT] private Set < Key > cachePutIfUntouched ( final Iterable < Bucket > buckets ) { final Map < Key , CasPut > payload = new HashMap <> ( ) ; final Set < Key > successes = new HashSet <> ( ) ; for ( final Bucket buck : buckets ) { if ( ! buck . isCacheable ( ) ) { successes . add ( buck . getKey ( ) ) ; continue ; } final Integer expirySeconds = cacheControl . getExpirySeconds ( buck . getKey ( ) ) ; if ( expirySeconds == null ) { successes . add ( buck . getKey ( ) ) ; continue ; } payload . put ( buck . getKey ( ) , new CasPut ( buck . identifiableValue , buck . getNextToStore ( ) , expirySeconds ) ) ; } successes . addAll ( this . memcache . putIfUntouched ( payload ) ) ; return successes ; }


Input:
Bulk get on keys getting the raw objects [CODESPLIT] private Map < Key , Object > cacheGetAll ( final Collection < Key > keys ) { try { return this . memcache . getAll ( keys ) ; } catch ( Exception ex ) { // Some sort of serialization error, just wipe out the values
 log . warn ( "Error fetching values from memcache, deleting keys" , ex ) ; this . memcache . deleteAll ( keys ) ; return new HashMap <> ( ) ; } }


Input: Basically a list comprehension of the keys for convenience . [CODESPLIT] public static Set < Key > keysOf ( final Collection < Bucket > buckets ) { return buckets . stream ( ) . map ( Bucket :: getKey ) . collect ( Collectors . toSet ( ) ) ; }


Input: Recursively go through the class hierarchy looking for the idMeta and parentMeta fields . [CODESPLIT] private void findKeyFields ( Class < ? > inspect , CreateContext ctx , Path path ) { if ( inspect == Object . class ) return ; findKeyFields ( inspect . getSuperclass ( ) , ctx , path ) ; for ( Field field : inspect . getDeclaredFields ( ) ) { if ( field . getAnnotation ( Id . class ) != null ) { if ( this . idMeta != null ) throw new IllegalStateException ( "Multiple @Id fields in the class hierarchy of " + clazz . getName ( ) ) ; if ( ( field . getType ( ) != Long . class ) && ( field . getType ( ) != long . class ) && ( field . getType ( ) != String . class ) ) throw new IllegalStateException ( "@Id field '" + field . getName ( ) + "' in " + inspect . getName ( ) + " must be of type Long, long, or String" ) ; Property prop = new FieldProperty ( ctx . getFactory ( ) , clazz , field ) ; Translator < Object , Object > translator = ctx . getTranslator ( new TypeKey <> ( prop ) , ctx , path . extend ( prop . getName ( ) ) ) ; this . idMeta = new PropertyPopulator <> ( prop , translator ) ; } else if ( field . getAnnotation ( Parent . class ) != null ) { if ( this . parentMeta != null ) throw new IllegalStateException ( "Multiple @Parent fields in the class hierarchy of " + clazz . getName ( ) ) ; if ( ! isAllowedParentFieldType ( field . getType ( ) ) ) throw new IllegalStateException ( "@Parent fields must be Ref<?>, Key<?>, or datastore Key. Illegal parent: " + field ) ; Property prop = new FieldProperty ( ctx . getFactory ( ) , clazz , field ) ; Translator < Object , Object > translator = ctx . getTranslator ( new TypeKey <> ( prop ) , ctx , path . extend ( prop . getName ( ) ) ) ; this . parentMeta = new PropertyPopulator <> ( prop , translator ) ; } } }


Input: Sets the key ( from the container ) onto the POJO id / parent fields . Also doublechecks to make sure that the key fields aren t present in the container which means we re in a very bad state . [CODESPLIT] public void setKey ( final P pojo , final FullEntity < ? > container , final LoadContext ctx , final Path containerPath ) { if ( container . contains ( idMeta . getProperty ( ) . getName ( ) ) ) throw new IllegalStateException ( "Datastore has a property present for the id field " + idMeta . getProperty ( ) + " which would conflict with the key: " + container ) ; if ( parentMeta != null && container . contains ( parentMeta . getProperty ( ) . getName ( ) ) ) throw new IllegalStateException ( "Datastore has a property present for the parent field " + parentMeta . getProperty ( ) + " which would conflict with the key: " + container ) ; this . setKey ( pojo , container . getKey ( ) , ctx , containerPath ) ; }


Input: Sets the key onto the POJO id / parent fields [CODESPLIT] @ SuppressWarnings ( "unchecked" ) private void setKey ( final P pojo , final IncompleteKey key , final LoadContext ctx , final Path containerPath ) { if ( ! clazz . isAssignableFrom ( pojo . getClass ( ) ) ) throw new IllegalArgumentException ( "Trying to use metadata for " + clazz . getName ( ) + " to set key of " + pojo . getClass ( ) . getName ( ) ) ; // If no key, don't need to do anything if ( key == null ) return ; idMeta . setValue ( pojo , Keys . getIdValue ( key ) , ctx , containerPath ) ; final com . google . cloud . datastore . Key parentKey = key . getParent ( ) ; if ( parentKey != null ) { if ( this . parentMeta == null ) throw new IllegalStateException ( "Loaded Entity has parent but " + clazz . getName ( ) + " has no @Parent" ) ; parentMeta . setValue ( pojo , ( Value ) KeyValue . of ( parentKey ) , ctx , containerPath ) ; } }


Input: Sets the key on a container from the POJO . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < K extends IncompleteKey > void setKey ( final FullEntity . Builder < K > container , final P pojo ) { final IncompleteKey rawKey = getIncompleteKey ( pojo ) ; if ( ! ( rawKey instanceof com . google . cloud . datastore . Key ) ) { // it's incomplete, make sure we can save it Preconditions . checkState ( isIdNumeric ( ) , "Cannot save an entity with a null String @Id: %s" , pojo ) ; } container . setKey ( ( K ) rawKey ) ; }


Input: Gets a key composed of the relevant id and parent fields in the object . [CODESPLIT] public IncompleteKey getIncompleteKey ( final P pojo ) { log . trace ( "Getting key from {}" , pojo ) ; if ( ! clazz . isAssignableFrom ( pojo . getClass ( ) ) ) throw new IllegalArgumentException ( "Trying to use metadata for " + clazz . getName ( ) + " to get key of " + pojo . getClass ( ) . getName ( ) ) ; final Object id = getId ( pojo ) ; final com . google . cloud . datastore . Key parent = getParentRaw ( pojo ) ; if ( id == null ) return factory . keys ( ) . createRawIncomplete ( parent , kind ) ; else return factory . keys ( ) . createRawAny ( parent , kind , id ) ; }


Input: Gets a key composed of the relevant id and parent fields in the object . [CODESPLIT] public com . google . cloud . datastore . Key getCompleteKey ( final P pojo ) { final com . google . cloud . datastore . IncompleteKey key = getIncompleteKey ( pojo ) ; if ( key instanceof com . google . cloud . datastore . Key ) return ( com . google . cloud . datastore . Key ) key ; else throw new IllegalArgumentException ( "You cannot create a Key for an object with a null @Id. Object was " + pojo ) ; }


Input: Sets the numeric id field [CODESPLIT] public void setLongId ( P pojo , Long id ) { if ( ! clazz . isAssignableFrom ( pojo . getClass ( ) ) ) throw new IllegalArgumentException ( "Trying to use metadata for " + clazz . getName ( ) + " to set key of " + pojo . getClass ( ) . getName ( ) ) ; this . idMeta . getProperty ( ) . set ( pojo , id ) ; }


Input: Get the contents of the [CODESPLIT] private com . google . cloud . datastore . Key getParentRaw ( P pojo ) { if ( parentMeta == null ) return null ; final Value < Object > value = parentMeta . getValue ( pojo , new SaveContext ( ) , Path . root ( ) ) ; return ( value == null || value . getType ( ) == ValueType . NULL ) ? null : ( com . google . cloud . datastore . Key ) value . get ( ) ; }


Input: Recursively register this subclass with all the superclass translators . This works because we cache translators uniquely in the factory . [CODESPLIT] private void registerSubclass ( final ClassTranslator < P > translator , final TypeKey < ? super P > superclassTypeKey , final CreateContext ctx , final Path path ) { if ( superclassTypeKey . getTypeAsClass ( ) == Object . class ) return ; @ SuppressWarnings ( "unchecked" ) final ClassTranslator < ? super P > superTranslator = create ( ( TypeKey ) superclassTypeKey , ctx , path ) ; superTranslator . registerSubclass ( translator ) ; registerSubclass ( translator , new TypeKey <> ( superclassTypeKey . getTypeAsClass ( ) . getSuperclass ( ) ) , ctx , path ) ; }


Input: Creates a type of class <tt > clazz< / tt > with <tt > arguments< / tt > as type arguments . <p > For example : <tt > parameterizedClass ( Map . class Integer . class String . class ) < / tt > returns the type <tt > Map&lt ; Integer String&gt ; < / tt > . [CODESPLIT] public static Type parameterizedClass ( Class < ? > clazz , Type ... arguments ) { return parameterizedInnerClass ( null , clazz , arguments ) ; }


Input: Creates a type of <tt > clazz< / tt > nested in <tt > owner< / tt > . [CODESPLIT] public static Type innerClass ( Type owner , Class < ? > clazz ) { return parameterizedInnerClass ( owner , clazz , ( Type [ ] ) null ) ; }


Input: Creates a type of <tt > clazz< / tt > with <tt > arguments< / tt > as type arguments nested in <tt > owner< / tt > . <p > In the ideal case this returns a { @link ParameterizedType } with all generic information in it . If some type arguments are missing or if the resulting type simply doesn t need any type parameters it returns the raw <tt > clazz< / tt > . Note that types with some parameters specified and others not don t exist in Java . <p > If the caller does not know the exact <tt > owner< / tt > type or <tt > arguments< / tt > <tt > null< / tt > should be given ( or { @link #parameterizedClass ( Class Type ... ) } or { @link #innerClass ( Type Class ) } could be used ) . If they are not needed ( non - generic owner and / or <tt > clazz< / tt > has no type parameters ) they will be filled in automatically . If they are needed but are not given the raw <tt > clazz< / tt > is returned . <p > The specified <tt > owner< / tt > may be any subtype of <tt > clazz . getDeclaringClass () < / tt > . It is automatically converted into the right parameterized version of the declaring class . If <tt > clazz< / tt > is a <tt > static< / tt > ( nested ) class the owner is not used . [CODESPLIT] public static Type parameterizedInnerClass ( Type owner , Class < ? > clazz , Type ... arguments ) { // never allow an owner on a class that doesn't have one if ( clazz . getDeclaringClass ( ) == null && owner != null ) { throw new IllegalArgumentException ( "Cannot specify an owner type for a top level class" ) ; } Type realOwner = transformOwner ( owner , clazz ) ; if ( arguments == null ) { if ( clazz . getTypeParameters ( ) . length == 0 ) { // no arguments known, but no needed so just use an empty argument list. // (we can still end up with a generic type if the owner is generic) arguments = new Type [ 0 ] ; } else { // missing type arguments, return the raw type return clazz ; } } else { if ( arguments . length != clazz . getTypeParameters ( ) . length ) { throw new IllegalArgumentException ( "Incorrect number of type arguments for [" + clazz + "]: " + "expected " + clazz . getTypeParameters ( ) . length + ", but got " + arguments . length ) ; } } // if the class and its owner simply have no parameters at all, this is not a parameterized type if ( ! GenericTypeReflector . isMissingTypeParameters ( clazz ) ) { return clazz ; } // if the owner type is missing type parameters and clazz is non-static, this is a raw type if ( realOwner != null && ! Modifier . isStatic ( clazz . getModifiers ( ) ) && GenericTypeReflector . isMissingTypeParameters ( realOwner ) ) { return clazz ; } ParameterizedType result = new ParameterizedTypeImpl ( clazz , arguments , realOwner ) ; checkParametersWithinBound ( result ) ; return result ; }


Input: Check if the type arguments of the given type are within the bounds declared on the type parameters . Only the type arguments of the type itself are checked the possible owner type is assumed to be valid . <p > It does not follow the checks defined in the <a href = http : // java . sun . com / docs / books / jls / third_edition / html / typesValues . html#4 . 5 > JLS< / a > because there are several problems with those ( see http : // stackoverflow . com / questions / 7003009 for one ) . Instead this applies some intuition and follows what Java compilers seem to do . [CODESPLIT] private static void checkParametersWithinBound ( ParameterizedType type ) { Type [ ] arguments = type . getActualTypeArguments ( ) ; TypeVariable < ? > [ ] typeParameters = ( ( Class < ? > ) type . getRawType ( ) ) . getTypeParameters ( ) ; // a map of type arguments in the type, to fill in variables in the bounds  VarMap varMap = new VarMap ( type ) ; // for every bound on every parameter for ( int i = 0 ; i < arguments . length ; i ++ ) { for ( Type bound : typeParameters [ i ] . getBounds ( ) ) { // replace type variables in the bound by their value Type replacedBound = varMap . map ( bound ) ; if ( arguments [ i ] instanceof WildcardType ) { WildcardType wildcardTypeParameter = ( WildcardType ) arguments [ i ] ; // Check if a type satisfying both the bounds of the variable and of the wildcard could exist // upper bounds must not be mutually exclusive for ( Type wildcardUpperBound : wildcardTypeParameter . getUpperBounds ( ) ) { if ( ! couldHaveCommonSubtype ( replacedBound , wildcardUpperBound ) ) { throw new TypeArgumentNotInBoundException ( arguments [ i ] , typeParameters [ i ] , bound ) ; } } // a lowerbound in the wildcard must satisfy every upperbound  for ( Type wildcardLowerBound : wildcardTypeParameter . getLowerBounds ( ) ) { if ( ! GenericTypeReflector . isSuperType ( replacedBound , wildcardLowerBound ) ) { throw new TypeArgumentNotInBoundException ( arguments [ i ] , typeParameters [ i ] , bound ) ; } } } else { if ( ! GenericTypeReflector . isSuperType ( replacedBound , arguments [ i ] ) ) { throw new TypeArgumentNotInBoundException ( arguments [ i ] , typeParameters [ i ] , bound ) ; } } } } }


Input: Checks if the intersection of two types is not empty . [CODESPLIT] private static boolean couldHaveCommonSubtype ( Type type1 , Type type2 ) { // this is an optimistically naive implementation. // if they are parameterized types their parameters need to be checked,... // so we're just a bit too lenient here Class < ? > erased1 = GenericTypeReflector . erase ( type1 ) ; Class < ? > erased2 = GenericTypeReflector . erase ( type2 ) ; // if they are both classes if ( ! erased1 . isInterface ( ) && ! erased2 . isInterface ( ) ) { // then one needs to be a subclass of another if ( ! erased1 . isAssignableFrom ( erased2 ) && ! erased2 . isAssignableFrom ( erased1 ) ) { return false ; } } return true ; }


Input: Transforms the given owner type into an appropriate one when constructing a parameterized type . [CODESPLIT] private static Type transformOwner ( Type givenOwner , Class < ? > clazz ) { if ( givenOwner == null ) { // be lenient: if this is an inner class but no owner was specified, assume a raw owner type // (or if there is no owner just return null) return clazz . getDeclaringClass ( ) ; } else { // If the specified owner is not of the declaring class' type, but instead a subtype, // transform it into the declaring class with the exact type parameters. // For example with "class StringOuter extends GenericOuter<String>", transform // "StringOuter.Inner" into "GenericOuter<String>.Inner", just like the Java compiler does. Type transformedOwner = GenericTypeReflector . getExactSuperType ( givenOwner , clazz . getDeclaringClass ( ) ) ; if ( transformedOwner == null ) { // null means it's not a supertype throw new IllegalArgumentException ( "Given owner type [" + givenOwner + "] is not appropriate for [" + clazz + "]: it should be a subtype of " + clazz . getDeclaringClass ( ) ) ; } if ( Modifier . isStatic ( clazz . getModifiers ( ) ) ) { // for a static inner class, the owner shouldn't have type parameters return GenericTypeReflector . erase ( transformedOwner ) ; } else { return transformedOwner ; } } }


Input: Creates a wildcard type with an upper bound . <p > For example <tt > wildcardExtends ( String . class ) < / tt > returns the type <tt > ? extends String< / tt > . [CODESPLIT] public static WildcardType wildcardExtends ( Type upperBound ) { if ( upperBound == null ) { throw new NullPointerException ( ) ; } return new WildcardTypeImpl ( new Type [ ] { upperBound } , new Type [ ] { } ) ; }


Input: Creates a wildcard type with a lower bound . <p > For example <tt > wildcardSuper ( String . class ) < / tt > returns the type <tt > ? super String< / tt > . [CODESPLIT] public static WildcardType wildcardSuper ( Type lowerBound ) { if ( lowerBound == null ) { throw new NullPointerException ( ) ; } return new WildcardTypeImpl ( new Type [ ] { Object . class } , new Type [ ] { lowerBound } ) ; }


Input: Checks not only the listed annotations but also annotations on the class . [CODESPLIT] public < A extends Annotation > A getAnnotationAnywhere ( Class < A > annotationType ) { A anno = getAnnotation ( annotationType ) ; if ( anno == null ) { Class < ? > clazz = ( Class < ? > ) GenericTypeReflector . erase ( type ) ; return clazz . getAnnotation ( annotationType ) ; } else { return anno ; } }


Input: Add / overwrite a SV . [CODESPLIT] public void add ( final Key < ? > key , final SessionValue < ? > value ) { if ( log . isTraceEnabled ( ) ) log . trace ( "Adding to session: {} -> {}" , key , value . getResult ( ) ) ; map . put ( key , value ) ; }


Input: Convenience method [CODESPLIT] public void addValue ( final Key < ? > key , final Object value ) { add ( key , new SessionValue <> ( new ResultNow <> ( value ) ) ) ; }


Input: Add all entries in the other session to this one [CODESPLIT] public void addAll ( final Session other ) { if ( log . isTraceEnabled ( ) ) log . trace ( "Adding all values to session: {}" , other . map . keySet ( ) ) ; map . putAll ( other . map ) ; }


Input: Eliminate any deferred operations against the entity . Used when an explicit save ( or delete ) was executed against the key so we no longer need the deferred operation . [CODESPLIT] public void undefer ( final Object keyOrEntity ) { if ( keyOrEntity instanceof Key < ? > ) { operations . remove ( ( Key < ? > ) keyOrEntity ) ; } else if ( keyOrEntity instanceof com . google . cloud . datastore . Key ) { operations . remove ( Key . create ( ( com . google . cloud . datastore . Key ) keyOrEntity ) ) ; } else if ( factory ( ) . keys ( ) . requiresAutogeneratedId ( keyOrEntity ) ) { // note might be FullEntity without complete key autogeneratedIdSaves . remove ( keyOrEntity ) ; } else { final Key < ? > key = factory ( ) . keys ( ) . keyOf ( keyOrEntity ) ; operations . remove ( key ) ; } }


Input:
Gets the result possibly from the session putting it in the session if necessary . Also will recursively prepare the session with [CODESPLIT] public < T > Result < T > load ( final Key < T > key ) { if ( key == null ) throw new NullPointerException ( "You tried to load a null key!" ) ; final Result < T > result = round . get ( key ) ; // If we are running a transaction, enlist the result so that it gets processed on commit even
 // if the client never materializes the result.
 if ( ofy . getTransaction ( ) != null ) ( ( PrivateAsyncTransaction ) ofy . getTransaction ( ) ) . enlist ( result ) ; // Now check to see if we need to recurse and add our parent(s) to the round
 if ( key . getParent ( ) != null ) { final KeyMetadata < ? > meta = ofy . factory ( ) . keys ( ) . getMetadata ( key ) ; // Is it really possible for this to be null?
 if ( meta != null ) { if ( meta . shouldLoadParent ( loadArrangement ) ) { load ( key . getParent ( ) ) ; } } } return result ; }


Input: Starts asychronous fetching of the batch . [CODESPLIT] public void execute ( ) { if ( round . needsExecution ( ) ) { Round old = round ; round = old . next ( ) ; old . execute ( ) ; } }


Input: Create a Ref for the key and maybe start a load operation depending on current load groups . [CODESPLIT] public < T > Ref < T > makeRef ( final Key < ? > rootEntity , final LoadConditions loadConditions , final Key < T > key ) { final Ref < T > ref = new LiveRef <> ( key , ofy ) ; if ( shouldLoad ( loadConditions ) ) { load ( key ) ; } return ref ; }


Input:
Asynchronously translate raw to processed ; might produce successive load operations as refs are filled in [CODESPLIT] public Result < Map < Key < ? > , Object > > translate ( final Result < Map < com . google . cloud . datastore . Key , Entity > > raw ) { return new ResultCache < Map < Key < ? > , Object > > ( ) { /** */ private LoadContext ctx ; /** */ @ Override public Map < Key < ? > , Object > nowUncached ( ) { final Map < Key < ? > , Object > result = new HashMap <> ( raw . now ( ) . size ( ) * 2 ) ; ctx = new LoadContext ( LoadEngine . this ) ; for ( final Entity ent : raw . now ( ) . values ( ) ) { final Key < ? > key = Key . create ( ent . getKey ( ) ) ; final Object entity = load ( ent , ctx ) ; result . put ( key , entity ) ; } return result ; } /**
			 * We need to execute the done() after the translated value has been set, otherwise we
			 * can produce an infinite recursion problem.
			 */ @ Override protected void postExecuteHook ( ) { ctx . done ( ) ; ctx = null ; } } ; }


Input: Fetch the keys from the async datastore using the current transaction context [CODESPLIT] public Result < Map < com . google . cloud . datastore . Key , Entity > > fetch ( Set < com . google . cloud . datastore . Key > keys ) { log . debug ( "Fetching {} keys: {}" , keys . size ( ) , keys ) ; final Future < Map < com . google . cloud . datastore . Key , Entity > > fut = datastore . get ( keys , readOptions . toArray ( new ReadOption [ readOptions . size ( ) ] ) ) ; return ResultAdapter . create ( fut ) ; }


Input: Converts a datastore entity into a typed pojo object [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < T > T load ( final BaseEntity < com . google . cloud . datastore . Key > ent , final LoadContext ctx ) { if ( ent == null ) return null ; final EntityMetadata < T > meta = ofy . factory ( ) . getMetadata ( ent . getKey ( ) . getKind ( ) ) ; if ( meta == null ) return ( T ) ent ; else return meta . load ( ent , ctx ) ; }


Input: Convenince method that creates a composite filter with any existing filter ( if present ) [CODESPLIT] public QueryDef andFilter ( final Filter addFilter ) { return filter ( this . filter == null ? addFilter : CompositeFilter . and ( this . filter , addFilter ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public DeleteIds parent ( final Object keyOrEntity ) { final Key < ? > parentKey = factory ( ) . keys ( ) . anythingToKey ( keyOrEntity ) ; return new DeleteTypeImpl ( deleter , type , parentKey ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Result < Void > id ( final String id ) { return ids ( Collections . singleton ( id ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Result < Void > ids ( final String ... ids ) { return ids ( Arrays . asList ( ids ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < S > Result < Void > ids ( final Iterable < S > ids ) { return this . deleter . keys ( factory ( ) . keys ( ) . createKeys ( parent , type , ids ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Map < K , V > get ( ) throws InterruptedException , ExecutionException { if ( this . pending != null ) { this . loaded . putAll ( this . pending . get ( ) ) ; this . pending = null ; } return this . loaded ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Map < K , V > get ( long timeout , TimeUnit unit ) throws InterruptedException , ExecutionException , TimeoutException { if ( this . pending != null ) { this . loaded . putAll ( this . pending . get ( timeout , unit ) ) ; this . pending = null ; } return this . loaded ; }


Input: <p > Gets the Key<T > given an object that might be a Key Key<T > or entity . < / p > [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < T > Key < T > anythingToKey ( final Object keyOrEntity ) { if ( keyOrEntity instanceof Key < ? > ) return ( Key < T > ) keyOrEntity ; else if ( keyOrEntity instanceof com . google . cloud . datastore . Key ) return Key . create ( ( com . google . cloud . datastore . Key ) keyOrEntity ) ; else if ( keyOrEntity instanceof Ref ) return ( ( Ref < T > ) keyOrEntity ) . key ( ) ; else if ( keyOrEntity instanceof FullEntity < ? > ) return Key . create ( getKey ( ( FullEntity < ? > ) keyOrEntity ) ) ; else return keyOf ( ( T ) keyOrEntity ) ; }


Input: <p > Gets the raw datstore Key given an object that might be a Key Key<T > or entity . < / p > [CODESPLIT] public com . google . cloud . datastore . Key anythingToRawKey ( final Object keyOrEntity ) { if ( keyOrEntity instanceof com . google . cloud . datastore . Key ) return ( com . google . cloud . datastore . Key ) keyOrEntity ; else if ( keyOrEntity instanceof Key < ? > ) return ( ( Key < ? > ) keyOrEntity ) . getRaw ( ) ; else if ( keyOrEntity instanceof Ref ) return ( ( Ref < ? > ) keyOrEntity ) . key ( ) . getRaw ( ) ; else if ( keyOrEntity instanceof FullEntity < ? > ) return getKey ( ( FullEntity < ? > ) keyOrEntity ) ; else return rawKeyOf ( keyOrEntity ) ; }


Input: Construct a Key from a Long or String id [CODESPLIT] public com . google . cloud . datastore . Key createRawAny ( final com . google . cloud . datastore . Key parent , final String kind , final Object id ) { if ( id instanceof String ) return createRaw ( parent , kind , ( String ) id ) ; else if ( id instanceof Long ) return createRaw ( parent , kind , ( Long ) id ) ; else throw new IllegalArgumentException ( "id '" + id + "' must be String or Long" ) ; }


Input: Construct a Key<? > from a Long or String id [CODESPLIT] public < T > Key < T > createKeyAny ( final Key < ? > parent , final Class < T > kind , final Object id ) { if ( id instanceof String ) return createKey ( parent , kind , ( String ) id ) ; else if ( id instanceof Long ) return createKey ( parent , kind , ( Long ) id ) ; else throw new IllegalArgumentException ( "id '" + id + "' must be String or Long" ) ; }


Input: Null - safe extraction of the raw key [CODESPLIT] public static com . google . cloud . datastore . Key raw ( final Key < ? > key ) { return key == null ? null : key . getRaw ( ) ; }


Input: Make a list of Key<? > s [CODESPLIT] public < T > List < Key < T > > createKeys ( final Key < ? > parent , final Class < T > kind , final Iterable < ? > ids ) { return StreamSupport . stream ( ids . spliterator ( ) , false ) . map ( id -> createKeyAny ( parent , kind , id ) ) . collect ( Collectors . toList ( ) ) ; }


Input: Gets the String or Long id from the key as a Value or null if incomplete [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public static < S > Value < S > getIdValue ( final IncompleteKey key ) { if ( key instanceof com . google . cloud . datastore . Key ) { final com . google . cloud . datastore . Key completeKey = ( com . google . cloud . datastore . Key ) key ; if ( completeKey . hasId ( ) ) return ( Value < S > ) LongValue . of ( completeKey . getId ( ) ) ; else return ( Value < S > ) StringValue . of ( completeKey . getName ( ) ) ; } else { return null ; } }


Input: Understands both the legacy format ag1zfnZvb2Rvb2R5bmUwcgcLEgFCGAEM and new format providing the key either way . [CODESPLIT] @ SneakyThrows public static com . google . cloud . datastore . Key fromUrlSafe ( final String urlSafeKey ) { if ( urlSafeKey . startsWith ( "a" ) ) { return KeyFormat . INSTANCE . parseOldStyleAppEngineKey ( urlSafeKey ) ; } else { return com . google . cloud . datastore . Key . fromUrlSafe ( urlSafeKey ) ; } }


Input: This version goes back to life without a transaction but preserves current options . We use the session from the parent ie life before transactions . [CODESPLIT] @ Override public ObjectifyImpl transactionless ( final ObjectifyImpl parent ) { return parent . makeNew ( next -> new TransactorNo ( next , parentTransactor . getSession ( ) ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < R > R execute ( final ObjectifyImpl parent , final TxnType txnType , final Work < R > work ) { switch ( txnType ) { case MANDATORY : case REQUIRED : case SUPPORTS : return work . run ( ) ; case NOT_SUPPORTED : return transactionless ( parent , work ) ; case NEVER : throw new IllegalStateException ( "MANDATORY transaction but no transaction present" ) ; case REQUIRES_NEW : return transactNew ( parent , Transactor . DEFAULT_TRY_LIMIT , work ) ; default : throw new IllegalStateException ( "Impossible, some unknown txn type" ) ; } }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < R > R transact ( final ObjectifyImpl parent , final Work < R > work ) { return work . run ( ) ; }


Input: We need to make sure the parentSession is the transactionless session not the session for our transaction . This gives proper transaction isolation . [CODESPLIT] @ Override public < R > R transactNew ( final ObjectifyImpl parent , final int limitTries , final Work < R > work ) { return transactionless ( parent ) . transactNew ( limitTries , work ) ; }


Input: / * [CODESPLIT] @ Override public Query < T > filter ( final Filter filter ) { final QueryImpl < T > q = createQuery ( ) ; q . addFilter ( filter ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Query < T > order ( String condition ) { QueryImpl < T > q = createQuery ( ) ; q . addOrder ( condition ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public LoadResult < T > id ( final String id ) { return loader . key ( this . makeKey ( id ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Map < Long , T > ids ( final Long ... ids ) { return ids ( Arrays . asList ( ids ) ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public Map < String , T > ids ( final String ... ids ) { return ids ( Arrays . asList ( ids ) ) ; }


Input:
/ * ( non - Javadoc ) [CODESPLIT] @ Override public < S > Map < S , T > ids ( final Iterable < S > ids ) { final Map < Key < T > , S > keymap = new LinkedHashMap <> ( ) ; for ( final S id : ids ) keymap . put ( this . makeKey ( id ) , id ) ; final Map < Key < T > , T > loaded = loader . keys ( keymap . keySet ( ) ) ; return ResultProxy . create ( Map . class , new ResultCache < Map < S , T > > ( ) { @ Override protected Map < S , T > nowUncached ( ) { final Map < S , T > proper = new LinkedHashMap <> ( loaded . size ( ) * 2 ) ; for ( final Map . Entry < Key < T > , T > entry : loaded . entrySet ( ) ) proper . put ( keymap . get ( entry . getKey ( ) ) , entry . getValue ( ) ) ; return proper ; } } ) ; } /**
	 * Make a key for the given id, which could be either string or long
	 */ private < T > Key < T > makeKey ( final Object id ) { final com . google . cloud . datastore . Key key = factory ( ) . keys ( ) . createRawAny ( Keys . raw ( this . parent ) , kind , id ) ; return Key . create ( key ) ; } /* (non-Javadoc)
	 * @see com.googlecode.objectify.cmd.LoadType#parent(java.lang.Object)
	 */ @ Override public LoadIds < T > parent  ( final Object keyOrEntity ) { final Key < T > parentKey = factory ( ) . keys ( ) . anythingToKey ( keyOrEntity ) ; return new LoadTypeImpl <> ( loader , kind , type , parentKey ) ; } /** */ private ObjectifyFactory factory  ( ) { return loader . getObjectifyImpl ( ) . factory ( ) ; } }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < R > R execute ( final ObjectifyImpl parent , final TxnType txnType , final Work < R > work ) { switch ( txnType ) { case MANDATORY : throw new IllegalStateException ( "MANDATORY transaction but no transaction present" ) ; case NOT_SUPPORTED : case NEVER : case SUPPORTS : return work . run ( ) ; case REQUIRED : case REQUIRES_NEW : return transact ( parent , work ) ; default : throw new IllegalStateException ( "Impossible, some unknown txn type" ) ; } }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public < R > R transact ( final ObjectifyImpl parent , final Work < R > work ) { return this . transactNew ( parent , DEFAULT_TRY_LIMIT , work ) ; }


Input:
/ * ( non - Javadoc ) [CODESPLIT] @ Override public < R > R transactNew ( final ObjectifyImpl parent , int limitTries , final Work < R > work ) { Preconditions . checkArgument ( limitTries >= 1 ) ; final int ORIGINAL_TRIES = limitTries ; while ( true ) { try { return transactOnce ( parent , work ) ; } catch ( DatastoreException ex ) { // This doesn't work because the SDK considers all transactions to be non-retryable. Objectify has always
 // assumed that transactions are idempotent and retries accordingly. So we have to explicitly check against
 // code 10, which is ABORTED. https://cloud.google.com/datastore/docs/concepts/errors
 //				if (!ex.isRetryable())
 //					throw ex;
 // I hate this so much. Sometimes the transaction gets closed by the datastore during contention and
 // then it proceeds to freak out and 503.
 if ( Code . ABORTED . getNumber ( ) == ex . getCode ( ) || ( Code . INVALID_ARGUMENT . getNumber ( ) == ex . getCode ( ) && ex . getMessage ( ) . contains ( "transaction closed" ) ) ) { // Continue to retry logic
 } else { throw ex ; } if ( -- limitTries > 0 ) { log . warn ( "Retrying {} failure for {}: {}" , ex . getReason ( ) , work , ex ) ; log . trace ( "Details of transaction failure" , ex ) ; try { // Do increasing backoffs with randomness
 Thread . sleep ( Math . min ( 10000 , ( long ) ( 0.5 * Math . random ( ) + 0.5 ) * 200 * ( ORIGINAL_TRIES - limitTries + 2 ) ) ) ; } catch ( InterruptedException ignored ) { } } else { throw new DatastoreException ( ex . getCode ( ) , "Failed retrying datastore " + ORIGINAL_TRIES + " times " , ex . getReason ( ) , ex ) ; } } } }


Input: One attempt at executing a transaction [CODESPLIT] private < R > R transactOnce ( final ObjectifyImpl parent , final Work < R > work ) { final ObjectifyImpl txnOfy = factory . open ( parent . getOptions ( ) , next -> new TransactorYes ( next , this ) ) ; boolean committedSuccessfully = false ; try { final R result = work . run ( ) ; txnOfy . flush ( ) ; txnOfy . getTransaction ( ) . commit ( ) ; committedSuccessfully = true ; return result ; } finally { if ( txnOfy . getTransaction ( ) . isActive ( ) ) { try { txnOfy . getTransaction ( ) . rollback ( ) ; } catch ( RuntimeException ex ) { log . error ( "Rollback failed, suppressing error" , ex ) ; } } txnOfy . close ( ) ; if ( committedSuccessfully ) { ( ( PrivateAsyncTransaction ) txnOfy . getTransaction ( ) ) . runCommitListeners ( ) ; } } }


Input: Tests whether a set of conditions match . [CODESPLIT] private boolean matches ( Object onPojo , If < ? , ? > [ ] conditions ) { if ( conditions == null ) return false ; Object value = this . get ( onPojo ) ; for ( If < ? , ? > condition : conditions ) { @ SuppressWarnings ( "unchecked" ) If < Object , Object > cond = ( If < Object , Object > ) condition ; if ( cond . matchesValue ( value ) ) return true ; if ( cond . matchesPojo ( onPojo ) ) return true ; } return false ; }


Input:
Get the current objectify instance associated with this ref [CODESPLIT] private Objectify ofy ( ) { // If we have an expired transaction context, we need a new context
 if ( ofy == null || ( ofy . getTransaction ( ) != null && ! ofy . getTransaction ( ) . isActive ( ) ) ) ofy = ObjectifyService . ofy ( ) ; return ofy ; }


Input: Might produce a caching version if caching is enabled . [CODESPLIT] public AsyncDatastore asyncDatastore ( final boolean enableGlobalCache ) { if ( this . entityMemcache != null && enableGlobalCache && this . registrar . isCacheEnabled ( ) ) return new CachingAsyncDatastore ( asyncDatastore ( ) , this . entityMemcache ) ; else return asyncDatastore ( ) ; }


Input:
<p > Construct an instance of the specified type . Objectify uses this method whenever possible to create instances of entities condition classes or other types ; by overriding this method you can substitute Guice or other dependency injection mechanisms . By default it constructs with a simple no - args constructor . < / p > [CODESPLIT] @ Override public < T > T construct ( final Class < T > type ) { // We do this instead of calling newInstance directly because this lets us work around accessiblity
 final Constructor < T > ctor = TypeUtils . getNoArgConstructor ( type ) ; return TypeUtils . newInstance ( ctor ) ; }


Input: <p > Construct a collection of the specified type and the specified size for use on a POJO field . You can override this with Guice or whatnot . < / p > [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < T extends Collection < ? > > T constructCollection ( final Class < T > type , final int size ) { if ( ( Class < ? > ) type == List . class || ( Class < ? > ) type == Collection . class ) return ( T ) new ArrayList <> ( size ) ; else if ( ( Class < ? > ) type == Set . class ) return ( T ) new HashSet <> ( ( int ) ( size * 1.5 ) ) ; else if ( ( Class < ? > ) type == SortedSet . class ) return ( T ) new TreeSet <> ( ) ; else return construct ( type ) ; }


Input: <p > Construct a map of the specified type for use on a POJO field . You can override this with Guice or whatnot . < / p > [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < T extends Map < ? , ? > > T constructMap ( final Class < T > type ) { if ( ( Class < ? > ) type == Map . class ) return ( T ) new HashMap <> ( ) ; else if ( ( Class < ? > ) type == SortedMap . class ) return ( T ) new TreeMap <> ( ) ; else return construct ( type ) ; }


Input:
Named differently so you don t accidentally use the Object form [CODESPLIT] @ SuppressWarnings ( "unchecked" ) public < T > EntityMetadata < T > getMetadataForEntity ( final T obj ) throws IllegalArgumentException { // Type erasure sucks
 return ( EntityMetadata < T > ) this . getMetadata ( obj . getClass ( ) ) ; }


Input: Allocates a single id from the allocator for the specified kind . Safe to use in concert with the automatic generator . This is just a convenience method for allocateIds () . [CODESPLIT] public < T > Key < T > allocateId ( final Class < T > clazz ) { return allocateIds ( clazz , 1 ) . iterator ( ) . next ( ) ; }


Input: <p > Preallocate multiple unique ids within the namespace of the specified entity class . These ids can be used in concert with the normal automatic allocation of ids when save () ing entities with null Long id fields . < / p > [CODESPLIT] public < T > KeyRange < T > allocateIds ( final Class < T > clazz , final int num ) { final String kind = Key . getKind ( clazz ) ; final IncompleteKey incompleteKey = datastore ( ) . newKeyFactory ( ) . setKind ( kind ) . newKey ( ) ; return allocate ( incompleteKey , num ) ; }


Input: Preallocate a contiguous range of unique ids within the namespace of the specified entity class and the parent key . These ids can be used in concert with the normal automatic allocation of ids when put () ing entities with null Long id fields . [CODESPLIT] public < T > KeyRange < T > allocateIds ( final Object parentKeyOrEntity , final Class < T > clazz , final int num ) { final Key < ? > parent = keys ( ) . anythingToKey ( parentKeyOrEntity ) ; final String kind = Key . getKind ( clazz ) ; final IncompleteKey incompleteKey = com . google . cloud . datastore . Key . newBuilder ( parent . getRaw ( ) , kind ) . build ( ) ; return allocate ( incompleteKey , num ) ; }


Input: Allocate num copies of the incompleteKey [CODESPLIT] private < T > KeyRange < T > allocate ( final IncompleteKey incompleteKey , final int num ) { final IncompleteKey [ ] allocations = new IncompleteKey [ num ] ; Arrays . fill ( allocations , incompleteKey ) ; final List < Key < T > > typedKeys = datastore ( ) . allocateId ( allocations ) . stream ( ) . map ( Key :: < T > create ) . collect ( Collectors . toList ( ) ) ; return new KeyRange <> ( typedKeys ) ; }


Input: The method to call at any time to get the current Objectify which may change depending on txn context . Normally you should use the static { [CODESPLIT] public Objectify ofy ( ) { final Deque < Objectify > stack = stacks . get ( ) ; if ( stack . isEmpty ( ) ) throw new IllegalStateException ( "You have not started an Objectify context. You are probably missing the " + "ObjectifyFilter. If you are not running in the context of an http request, see the " + "ObjectifyService.run() method." ) ; return stack . getLast ( ) ; }


Input: <p > Start a scope of work . This is the outermost scope of work typically created by the ObjectifyFilter or by one of the methods on ObjectifyService . You need one of these to do anything at all . < / p > [CODESPLIT] public ObjectifyImpl open ( ) { final ObjectifyImpl objectify = new ObjectifyImpl ( this ) ; stacks . get ( ) . add ( objectify ) ; return objectify ; }


Input: This is only public because it is used from the impl package ; don t use this as a public API [CODESPLIT] public ObjectifyImpl open ( final ObjectifyOptions opts , final TransactorSupplier transactorSupplier ) { final ObjectifyImpl objectify = new ObjectifyImpl ( this , opts , transactorSupplier ) ; stacks . get ( ) . add ( objectify ) ; return objectify ; }


Input: Pops context off of stack after a transaction completes . For internal housekeeping only . [CODESPLIT] public void close ( final Objectify ofy ) { final Deque < Objectify > stack = stacks . get ( ) ; if ( stack . isEmpty ( ) ) throw new IllegalStateException ( "You have already destroyed the Objectify context." ) ; final Objectify popped = stack . removeLast ( ) ; assert popped == ofy : "Mismatched objectify instances; somehow the stack was corrupted" ; }


Input: / * [CODESPLIT] @ Override public Translator < Value < Object > , Object > create ( final TypeKey < Value < Object > > tk , final CreateContext ctx , final Path path ) { if ( ! tk . isAssignableTo ( Value . class ) ) return null ; return new NullSafeTranslator < Value < Object > , Object > ( ) { @ Override protected Value < Object > loadSafe ( final Value < Object > value , final LoadContext ctx , final Path path ) throws SkipException { return value ; } @ Override protected Value < Object > saveSafe ( final Value < Object > pojo , final boolean index , final SaveContext ctx , final Path path ) throws SkipException { return pojo ; } } ; }


Input: <p > Runs one unit of work making the root Objectify context available . This does not start a transaction but it makes the static ofy () method return an appropriate object . < / p > [CODESPLIT] public static < R > R run ( final Work < R > work ) { try ( Closeable closeable = begin ( ) ) { return work . run ( ) ; } }


Input: The datastore has a weird behavior of reordering values in a list so that indexed ones come before nonindexed ones . This can really mess up ordered lists . So if we find a heterogeneous list we need to force index everything . [CODESPLIT] public static void homogenizeIndexes ( final List < Value < ? > > list ) { if ( isIndexHomogeneous ( list ) ) return ; for ( int i = 0 ; i < list . size ( ) ; i ++ ) { final Value < ? > value = list . get ( i ) ; if ( value . excludeFromIndexes ( ) ) list . set ( i , index ( value , true ) ) ; } }


Input: Coerces the value to be a number of the specified type ; needed because all numbers come back from the datastore as Long / Double and this screws up any type that expects something smaller . We don t need to worry about primitive types because we wrapped the class earlier . [CODESPLIT] private Number coerceNumber ( final Number value , final Class < ? > type ) { if ( type == Byte . class ) return value . byteValue ( ) ; else if ( type == Short . class ) return value . shortValue ( ) ; else if ( type == Integer . class ) return value . intValue ( ) ; else if ( type == Long . class ) return value . longValue ( ) ; else throw new IllegalArgumentException ( ) ; // should be impossible }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > filterKey ( String condition , Object value ) { QueryImpl < T > q = createQuery ( ) ; q . addFilter ( KEY_RESERVED_PROPERTY + " " + condition . trim ( ) , value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > ancestor ( Object keyOrEntity ) { QueryImpl < T > q = createQuery ( ) ; q . setAncestor ( keyOrEntity ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > limit ( int value ) { QueryImpl < T > q = createQuery ( ) ; q . setLimit ( value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > offset ( int value ) { QueryImpl < T > q = createQuery ( ) ; q . setOffset ( value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > startAt ( Cursor value ) { QueryImpl < T > q = createQuery ( ) ; q . setStartCursor ( value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > endAt ( Cursor value ) { QueryImpl < T > q = createQuery ( ) ; q . setEndCursor ( value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > chunk ( int value ) { QueryImpl < T > q = createQuery ( ) ; q . setChunk ( value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > hybrid ( boolean force ) { QueryImpl < T > q = createQuery ( ) ; q . setHybrid ( force ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryKeys < T > keys ( ) { QueryImpl < T > q = createQuery ( ) ; q . checkKeysOnlyOk ( ) ; return new QueryKeysImpl <> ( q ) ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > distinct ( boolean value ) { QueryImpl < T > q = createQuery ( ) ; q . setDistinct ( value ) ; return q ; }


Input: / * ( non - Javadoc ) [CODESPLIT] @ Override public QueryImpl < T > project ( String ... fields ) { QueryImpl < T > q = createQuery ( ) ; q . addProjection ( fields ) ; return q ; }


Input: Key . create ( Blah . class id ) is easier to type than new Key<Blah > ( Blah . class id ) [CODESPLIT] public static < T > Ref < T > create ( Key < T > key ) { if ( key == null ) throw new NullPointerException ( "Cannot create a Ref from a null key" ) ; return new LiveRef <> ( key ) ; }


Input: Creates a Ref from a registered pojo entity [CODESPLIT] public static < T > Ref < T > create ( T value ) { Key < T > key = Key . create ( value ) ; return create ( key ) ; }


Input: Obtain the entity value throwing an exception if the entity was not found . [CODESPLIT] final public T safe ( ) throws NotFoundException { T t = this . get ( ) ; if ( t == null ) throw new NotFoundException ( key ( ) ) ; else return t ; }


Input: Adds a value to the set associated with the key . [CODESPLIT] public boolean add ( K key , V value ) { List < V > list = this . get ( key ) ; if ( list == null ) { list = new ArrayList <> ( ) ; this . put ( key , list ) ; } return list . add ( value ) ; }


Input: This version also checks to see if we are done and we still need to call the trigger . If so it calls it . [CODESPLIT] @ Override public boolean isDone ( ) { boolean done = this . raw . isDone ( ) ; if ( ! triggered && done ) { this . triggered = true ; PendingFutures . removePending ( this ) ; this . trigger ( ) ; } return done ; }


Input: Clever enough to recognize that an empty set of conditions means Always . [CODESPLIT] public If < ? , ? > [ ] generateIfConditions ( Class < ? extends If < ? , ? > > [ ] ifClasses , Field field ) { if ( ifClasses . length == 0 ) return ALWAYS ; If < ? , ? > [ ] result = new If < ? , ? > [ ifClasses . length ] ; for ( int i = 0 ; i < ifClasses . length ; i ++ ) { Class < ? extends If < ? , ? > > ifClass = ifClasses [ i ] ; result [ i ] = this . createIf ( ifClass , field ) ; // Sanity check the generic If class types to ensure that they match the actual types of the field & entity. Type valueType = GenericTypeReflector . getTypeParameter ( ifClass , If . class . getTypeParameters ( ) [ 0 ] ) ; Class < ? > valueClass = GenericTypeReflector . erase ( valueType ) ; Type pojoType = GenericTypeReflector . getTypeParameter ( ifClass , If . class . getTypeParameters ( ) [ 1 ] ) ; Class < ? > pojoClass = GenericTypeReflector . erase ( pojoType ) ; if ( ! TypeUtils . isAssignableFrom ( valueClass , field . getType ( ) ) ) throw new IllegalStateException ( "Cannot use If class " + ifClass . getName ( ) + " on " + field + " because you cannot assign " + field . getType ( ) . getName ( ) + " to " + valueClass . getName ( ) ) ; if ( ! TypeUtils . isAssignableFrom ( pojoClass , field . getDeclaringClass ( ) ) ) throw new IllegalStateException ( "Cannot use If class " + ifClass . getName ( ) + " on " + field + " because the containing class " + field . getDeclaringClass ( ) . getName ( ) + " is not compatible with " + pojoClass . getName ( ) ) ; } return result ; }


Input: Call this when a load process completes . Executes anything in the batch and then executes any delayed operations . [CODESPLIT] public void done ( ) { engine . execute ( ) ; while ( deferred != null ) { final List < Runnable > runme = deferred ; deferred = null ; // reset this because it might get filled with more for ( final Runnable run : runme ) { log . trace ( "Executing {}" , run ) ; run . run ( ) ; } } }


Input: Create a Ref for the key and maybe start a load operation depending on current load groups . [CODESPLIT] public < T > Ref < T > loadRef ( Key < T > key , LoadConditions loadConditions ) { return engine . makeRef ( currentRoot , loadConditions , key ) ; }


Input: Delays an operation until the context is done () . Typically this is for lifecycle methods . [CODESPLIT] public void defer ( Runnable runnable ) { if ( this . deferred == null ) this . deferred = new ArrayList <> ( ) ; log . trace ( "Deferring: {}" , runnable ) ; this . deferred . add ( runnable ) ; }


Input: Get the container object which is appropriate for the specified property . Go up the chain looking for a compatible type ; the first one found is the container . If nothing found throw an exception . [CODESPLIT] public Object getContainer ( Type containerType , Path path ) { Class < ? > containerClass = GenericTypeReflector . erase ( containerType ) ; Iterator < Object > containersIt = containers . descendingIterator ( ) ; // We have always entered the current 'this' context when processing properties, so the first thing // we get will always be 'this'. So skip that and the first matching owner should be what we want. containersIt . next ( ) ; while ( containersIt . hasNext ( ) ) { Object potentialContainer = containersIt . next ( ) ; if ( containerClass . isAssignableFrom ( potentialContainer . getClass ( ) ) ) return potentialContainer ; } throw new IllegalStateException ( "No container matching " + containerType + " in " + containers + " at path " + path ) ; }


Input: We re just tracking statistics so we don t really need to worry about these stepping on each other ; if there s a hit or miss lost no big deal . [CODESPLIT] private Stat getStat ( String kind ) { Stat stat = this . stats . get ( kind ) ; if ( stat == null ) { stat = new Stat ( ) ; this . stats . put ( kind , stat ) ; } return stat ; }


Input:
Quietly perform the get () on a future [CODESPLIT] public static < T > T quietGet ( Future < T > future ) { try { return future . get ( ) ; } catch ( Exception ex ) { unwrapAndThrow ( ex ) ; return null ; // just to make the compiler happy
 } }


Input: Properly unwraps ExecutionException throwing the relevant original cause . Otherwise RuntimeExceptions get thrown and checked exceptions get wrapped in a RuntimeException . [CODESPLIT] public static void unwrapAndThrow ( Throwable ex ) { if ( ex instanceof RuntimeException ) throw ( RuntimeException ) ex ; else if ( ex instanceof Error ) throw ( Error ) ex ; else if ( ex instanceof ExecutionException ) unwrapAndThrow ( ex . getCause ( ) ) ; else throw new UndeclaredThrowableException ( ex ) ; }


Input: Coerces the value to be a number of the specified type ; needed because all numbers come back from the datastore as Long / Double and this screws up any type that expects something smaller . We don t need to worry about primitive types because we wrapped the class earlier . [CODESPLIT] private Number coerceNumber ( final Number value , final Class < ? > type ) { if ( type == Float . class ) return value . floatValue ( ) ; else if ( type == Double . class ) return value . doubleValue ( ) ; else throw new IllegalArgumentException ( ) ; // should be impossible }


Input: Obtains the Translator appropriate for this type and annotations . May be a cached translator ; if not one will be discovered and cached . [CODESPLIT] public < P , D > Translator < P , D > get ( final TypeKey tk , final CreateContext ctx , final Path path ) { Translator < ? , ? > translator = translators . get ( tk ) ; if ( translator == null ) { translator = create ( tk , ctx , path ) ; translators . put ( tk , translator ) ; } //noinspection unchecked return ( Translator < P , D > ) translator ; }


Input: Get the translator for a root entity class [CODESPLIT] public < P > Translator < P , FullEntity < ? > > getRoot ( final Class < P > clazz ) { return get ( new TypeKey ( clazz ) , new CreateContext ( fact ) , Path . root ( ) ) ; }


Input: Create a translator from scratch by going through the discovery process . [CODESPLIT] private Translator < ? , ? > create ( final TypeKey tk , final CreateContext ctx , final Path path ) { for ( final TranslatorFactory < ? , ? > trans : this . translatorFactories ) { @ SuppressWarnings ( "unchecked" ) final Translator < ? , ? > soFar = trans . create ( tk , ctx , path ) ; if ( soFar != null ) return soFar ; } throw new IllegalArgumentException ( "Don't know how to translate " + tk . getType ( ) + " with annotations " + Arrays . toString ( tk . getAnnotations ( ) ) ) ; }


Input: Gets the appropriate value from the container and sets it on the appropriate field of the pojo . [CODESPLIT] @ Override public void load ( final FullEntity < ? > container , final LoadContext ctx , final Path containerPath , final P intoPojo ) { try { if ( translator instanceof Recycles ) ctx . recycle ( property . get ( intoPojo ) ) ; final Value < D > value = ( translator instanceof Synthetic ) ? null : getPropertyFromContainer ( container , containerPath ) ; // will throw SkipException if property not present setValue ( intoPojo , value , ctx , containerPath ) ; } catch ( SkipException ex ) { // Irrelevant } }


Input: Gets the relevant property from the container detecting alsoload collisions . [CODESPLIT] private Value < D > getPropertyFromContainer ( final FullEntity < ? > container , final Path containerPath ) { String foundName = null ; Value < D > value = null ; for ( String name : property . getLoadNames ( ) ) { if ( container . contains ( name ) ) { if ( foundName != null ) throw new IllegalStateException ( "Collision trying to load field; multiple name matches for '" + property . getName ( ) + "' at '" + containerPath . extend ( foundName ) + "' and '" + containerPath . extend ( name ) + "'" ) ; //noinspection unchecked value = container . getValue ( name ) ; foundName = name ; } } if ( foundName == null ) throw new SkipException ( ) ; else return value ; }


Input: Set this raw datastore value on the relevant property of the pojo doing whatever translations are necessary . [CODESPLIT] public void setValue ( final Object pojo , final Value < D > value , final LoadContext ctx , final Path containerPath ) throws SkipException { final Path propertyPath = containerPath . extend ( property . getName ( ) ) ; final P loaded = translator . load ( value , ctx , propertyPath ) ; setOnPojo ( pojo , loaded , ctx , propertyPath ) ; }


Input: Sets the property on the pojo to the value . The value should already be translated . TODO : Sensitive to the value possibly being a Result<? > wrapper in which case it enqueues the set operation until the loadcontext is done . [CODESPLIT] private void setOnPojo ( final Object pojo , final P value , final LoadContext ctx , final Path path ) { if ( log . isTraceEnabled ( ) ) log . trace ( LogUtils . msg ( path , "Setting property " + property . getName ( ) + " to " + value ) ) ; property . set ( pojo , value ) ; }


Input: Gets the appropriate field value from the pojo and puts it in the container at the appropriate prop name and with the appropriate indexing . [CODESPLIT] @ Override public void save ( final P onPojo , boolean index , final SaveContext ctx , final Path containerPath , final FullEntity . Builder < ? > into ) { if ( property . isSaved ( onPojo ) ) { // Look for an override on indexing final Boolean propertyIndexInstruction = property . getIndexInstruction ( onPojo ) ; if ( propertyIndexInstruction != null ) index = propertyIndexInstruction ; @ SuppressWarnings ( "unchecked" ) final P value = ( P ) property . get ( onPojo ) ; try { final Path propPath = containerPath . extend ( property . getName ( ) ) ; final Value < D > propValue = translator . save ( value , index , ctx , propPath ) ; into . set ( property . getName ( ) , propValue ) ; } catch ( SkipException ex ) { // No problem, do nothing } } }


Input: Get the value for the property and translate it into datastore format . [CODESPLIT] public Value < D > getValue ( final Object pojo , final SaveContext ctx , final Path containerPath ) { @ SuppressWarnings ( "unchecked" ) final P value = ( P ) property . get ( pojo ) ; return translator . save ( value , false , ctx , containerPath . extend ( property . getName ( ) ) ) ; }


Input: Write any extensions that may exist in a message . [CODESPLIT] @ SuppressWarnings ( "unchecked" ) protected final < EM extends ExtendableMessage < EM > > void writeExtensions ( EM msg , JsonGenerator gen ) throws IOException { boolean openExt = false ; for ( Map . Entry < FieldDescriptor , Object > field : msg . getAllFields ( ) . entrySet ( ) ) { FieldDescriptor fd = field . getKey ( ) ; if ( fd . isExtension ( ) ) { if ( fd . isRepeated ( ) ) { List < Object > extValue = ( List < Object > ) field . getValue ( ) ; if ( ! extValue . isEmpty ( ) ) { OpenRtbJsonExtWriter < Object > extWriter = factory . getWriter ( msg . getClass ( ) , extValue . get ( 0 ) . getClass ( ) , fd . getName ( ) ) ; if ( extWriter != null ) { openExt = openExt ( gen , openExt ) ; extWriter . writeRepeated ( extValue , gen ) ; } } } else { Object extValue = field . getValue ( ) ; OpenRtbJsonExtWriter < Object > extWriter = factory . getWriter ( msg . getClass ( ) , extValue . getClass ( ) , fd . getName ( ) ) ; if ( extWriter != null ) { openExt = openExt ( gen , openExt ) ; extWriter . writeSingle ( extValue , gen ) ; } } } } if ( openExt ) { gen . writeEndObject ( ) ; } }


Input: Writes a string that represents a ContentCategory s JSON name returning success status . If the factory is in strict mode the category name is validated . [CODESPLIT] protected final boolean writeContentCategory ( String cat , JsonGenerator gen ) throws IOException { if ( ! factory . isStrict ( ) || OpenRtbUtils . categoryFromName ( cat ) != null ) { gen . writeString ( cat ) ; return true ; } else { return false ; } }


Input: Writes an array of ContentCategory if not empty . [CODESPLIT] protected final void writeContentCategories ( String fieldName , List < String > cats , JsonGenerator gen ) throws IOException { if ( ! cats . isEmpty ( ) ) { gen . writeArrayFieldStart ( fieldName ) ; for ( String cat : cats ) { writeContentCategory ( cat , gen ) ; } gen . writeEndArray ( ) ; } }


Input: Processes the raw snippet that was set by the bid making any transformations necessary . [CODESPLIT] public String process ( SnippetProcessorContext ctx , String snippet ) { checkNotNull ( ctx ) ; StringBuilder sb = ctx . builder ( ) ; sb . setLength ( 0 ) ; String currSnippet = snippet ; boolean processedMacros = false ; int snippetPos = 0 ; int macroPos = currSnippet . indexOf ( "${" ) ; while ( macroPos != - 1 ) { sb . append ( currSnippet . substring ( snippetPos , macroPos ) ) ; int macroEnd = processMacroAt ( ctx , currSnippet , macroPos ) ; if ( macroEnd == - 1 ) { sb . append ( "${" ) ; snippetPos = macroPos + 2 ; } else { snippetPos = macroEnd ; processedMacros = true ; } macroPos = currSnippet . indexOf ( "${" , snippetPos ) ; } if ( processedMacros ) { sb . append ( currSnippet , snippetPos , currSnippet . length ( ) ) ; currSnippet = sb . toString ( ) ; } sb . setLength ( 0 ) ; String ret = urlEncode ( ctx , currSnippet ) ; sb . setLength ( 0 ) ; return ret ; }


Input: Serializes a { [CODESPLIT] public String writeBidRequest ( BidRequest req ) throws IOException { try ( StringWriter writer = new StringWriter ( ) ) { writeBidRequest ( req , writer ) ; return writer . toString ( ) ; } }


Input: Serializes a { @link BidRequest } to JSON streamed into an { @link Writer } . [CODESPLIT] public void writeBidRequest ( BidRequest req , Writer writer ) throws IOException { JsonGenerator gen = factory ( ) . getJsonFactory ( ) . createGenerator ( writer ) ; writeBidRequest ( req , gen ) ; }


Input: Serializes a { @link BidRequest } to JSON streamed into an { @link OutputStream } . [CODESPLIT] public void writeBidRequest ( BidRequest req , OutputStream os ) throws IOException { JsonGenerator gen = factory ( ) . getJsonFactory ( ) . createGenerator ( os ) ; writeBidRequest ( req , gen ) ; }


Input: Serializes a { [CODESPLIT] public final void writeBidRequest ( BidRequest req , JsonGenerator gen ) throws IOException { gen . writeStartObject ( ) ; writeBidRequestFields ( req , gen ) ; writeExtensions ( req , gen ) ; gen . writeEndObject ( ) ; gen . flush ( ) ; }


Input: Serializes a { [CODESPLIT] public String writeBidResponse ( BidResponse resp ) throws IOException { try ( StringWriter writer = new StringWriter ( ) ) { writeBidResponse ( resp , writer ) ; return writer . toString ( ) ; } }