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

com.netflix.hollow.jsonadapter.ObjectFieldMapping Maven / Gradle / Ivy

There is a newer version: 7.11.0
Show newest version
/*
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */
package com.netflix.hollow.jsonadapter;

import com.netflix.hollow.core.schema.HollowObjectSchema;
import com.netflix.hollow.core.write.HollowObjectTypeWriteState;
import com.netflix.hollow.core.write.HollowObjectWriteRecord;
import com.netflix.hollow.core.write.HollowWriteStateEngine;
import com.netflix.hollow.jsonadapter.field.FieldProcessor;
import java.util.HashMap;
import java.util.Map;

public class ObjectFieldMapping {

    private final HollowWriteStateEngine stateEngine;
    private final String typeName;
    private final HollowJsonAdapter populator;
    private final Map mappedFieldPaths;
    private final RemappingBuilderInstruction rootInstruction;
    private final Map writeRecords;

    public ObjectFieldMapping(String typeName, HollowJsonAdapter populator) {
        this.stateEngine = populator.stateEngine;
        this.typeName = typeName;
        this.populator = populator;
        HollowObjectTypeWriteState typeState = (HollowObjectTypeWriteState) stateEngine.getTypeState(typeName);
        HollowObjectWriteRecord writeRec = new HollowObjectWriteRecord(typeState.getSchema());
        this.rootInstruction = new RemappingBuilderInstruction(writeRec, typeState);
        this.mappedFieldPaths = new HashMap();
        this.writeRecords = new HashMap();

        mapAllPaths((HollowObjectSchema)stateEngine.getSchema(typeName));
    }

    private ObjectFieldMapping(String typeName, HollowJsonAdapter populator, Map mappedFieldPaths, RemappingBuilderInstruction rootInstruction, Map writeRecords) {
        this.stateEngine = populator.stateEngine;
        this.typeName = typeName;
        this.populator = populator;
        this.rootInstruction = rootInstruction;
        this.mappedFieldPaths = mappedFieldPaths;
        this.writeRecords = writeRecords;
    }

    public int build(int passthroughOrdinal) {
        int ordinal = rootInstruction.executeInstruction(passthroughOrdinal);

        for(Map.Entry entry : writeRecords.entrySet())
            entry.getValue().reset();

        return ordinal;
    }

    private void mapAllPaths(HollowObjectSchema schema) {
        for(int i=0;i entry : mappedFieldPaths.entrySet()) {
            if(fieldProcessor.getEntityName().equals(entry.getValue().getTypeName())
                    && fieldProcessor.getFieldName().equals(entry.getValue().getFieldName())) {
                entry.getValue().setFieldProcessor(fieldProcessor);
                return;
            }

            if(fieldProcessor.getEntityName().equals(entry.getValue().getUnmappedTypeName())
                    && fieldProcessor.getFieldName().equals(entry.getValue().getUnmappedFieldName())) {
                entry.getValue().setFieldProcessor(fieldProcessor);
                return;
            }
        }
    }

    private ObjectMappedFieldPath addPathMapping(String fieldName, String[] fieldPaths, RemappingBuilderInstruction instruction, int idx) {
        if(idx < fieldPaths.length - 1) {
            RemappingBuilderInstruction childInstruction = instruction.childrenRecs.get(fieldPaths[idx]);
            HollowObjectSchema schema = instruction.typeState.getSchema();
            String referencedType = schema.getReferencedType(fieldPaths[idx]);

            if(childInstruction == null) {
                HollowObjectTypeWriteState childTypeState = (HollowObjectTypeWriteState) stateEngine.getTypeState(referencedType);
                HollowObjectWriteRecord childWriteRec = getWriteRecord(childTypeState.getSchema());

                childInstruction = new RemappingBuilderInstruction(childWriteRec, childTypeState);
                instruction.addChildInstruction(fieldPaths[idx], childInstruction);
            }

            return addPathMapping(fieldName, fieldPaths, childInstruction, idx+1);
        }

        HollowObjectSchema schema = instruction.rec.getSchema();
        String remappedFieldName = fieldPaths[idx];

        return new ObjectMappedFieldPath(instruction.rec, remappedFieldName, typeName, fieldName, schema.getPosition(remappedFieldName), findFieldProcessor(typeName, fieldName, schema.getName(), remappedFieldName));
    }

    private FieldProcessor findFieldProcessor(String typeName, String fieldName, String mappedTypeName, String mappedFieldName) {
        FieldProcessor fp = populator.getFieldProcessor(typeName, fieldName);
        if(fp != null)
            return fp;

        return populator.getFieldProcessor(mappedTypeName, mappedFieldName);
    }

    private HollowObjectWriteRecord getWriteRecord(HollowObjectSchema schema) {
        HollowObjectWriteRecord writeRecord = writeRecords.get(schema.getName());
        if(writeRecord == null) {
            writeRecord = new HollowObjectWriteRecord(schema);
            writeRecords.put(schema.getName(), writeRecord);
        }
        return writeRecord;
    }


    private class RemappingBuilderInstruction {
        private final HollowObjectWriteRecord rec;
        private final HollowObjectTypeWriteState typeState;
        private final Map childrenRecs;

        public RemappingBuilderInstruction(HollowObjectWriteRecord rec, HollowObjectTypeWriteState typeState) {
            this(rec, typeState, new HashMap());
        }

        private RemappingBuilderInstruction(HollowObjectWriteRecord rec, HollowObjectTypeWriteState typeState, Map childrenRecs) {
            this.rec = rec;
            this.typeState = typeState;
            this.childrenRecs = childrenRecs;
        }

        public void addChildInstruction(String fieldName, RemappingBuilderInstruction instruction) {
            childrenRecs.put(fieldName, instruction);
        }

        public int executeInstruction(int passthroughOrdinal) {
            for(Map.Entry childEntry : childrenRecs.entrySet()) {
                int childOrdinal = childEntry.getValue().executeInstruction(-1);
                rec.setReference(childEntry.getKey(), childOrdinal);
            }

            if(passthroughOrdinal != -1)
                rec.setReference("passthrough", passthroughOrdinal);

            return typeState.add(rec);
        }

        public RemappingBuilderInstruction clone(Map clonedWriteRecords) {
            Map childClones = new HashMap();
            for(Map.Entry childEntry : childrenRecs.entrySet())
                childClones.put(childEntry.getKey(), childEntry.getValue().clone(clonedWriteRecords));

            HollowObjectWriteRecord clonedRec = clonedWriteRecords.get(rec.getSchema().getName());

            return new RemappingBuilderInstruction(clonedRec, typeState, childClones);
        }

    }

    @Override
    public ObjectFieldMapping clone() {
        Map clonedWriteRecords = new HashMap();
        for(Map.Entry recEntry : writeRecords.entrySet()) {
            clonedWriteRecords.put(recEntry.getKey(), new HollowObjectWriteRecord(recEntry.getValue().getSchema()));
        }

        Map clonedMappedFieldPaths = new HashMap();
        for(Map.Entry fieldEntry : mappedFieldPaths.entrySet()) {
            ObjectMappedFieldPath original = fieldEntry.getValue();
            HollowObjectWriteRecord clonedWriteRecord = clonedWriteRecords.get(original.getWriteRecord().getSchema().getName());
            clonedMappedFieldPaths.put(fieldEntry.getKey(), new ObjectMappedFieldPath(clonedWriteRecord, original.getFieldName(), original.getUnmappedTypeName(), original.getUnmappedFieldName(), original.getFieldPosition(), original.getFieldProcessor()));
        }

        return new ObjectFieldMapping(typeName, populator, clonedMappedFieldPaths, rootInstruction.clone(clonedWriteRecords), clonedWriteRecords);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy