nl.knaw.huygens.timbuctoo.tools.importer.JsonImporter.java Source code

Java tutorial

Introduction

Here is the source code for nl.knaw.huygens.timbuctoo.tools.importer.JsonImporter.java

Source

package nl.knaw.huygens.timbuctoo.tools.importer;

/*
 * #%L
 * Timbuctoo tools
 * =======
 * Copyright (C) 2012 - 2015 Huygens ING
 * =======
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public 
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 * #L%
 */

import java.io.File;
import java.util.Map;

import nl.knaw.huygens.timbuctoo.Repository;
import nl.knaw.huygens.timbuctoo.config.TypeRegistry;
import nl.knaw.huygens.timbuctoo.index.IndexManager;
import nl.knaw.huygens.timbuctoo.model.DomainEntity;
import nl.knaw.huygens.timbuctoo.model.Reference;
import nl.knaw.huygens.timbuctoo.model.Relation;
import nl.knaw.huygens.timbuctoo.model.RelationType;
import nl.knaw.huygens.timbuctoo.tools.config.ToolsInjectionModule;
import nl.knaw.huygens.timbuctoo.tools.process.Progress;
import nl.knaw.huygens.timbuctoo.util.Files;

import org.apache.commons.io.LineIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Maps;
import com.google.inject.Injector;

/**
 * Imports json files from a directory.
 * The import directory must contain a file "import.txt" specifying the json files to read.
 * <p>
 * Usage:<pre>
 * java nl.knaw.huygens.timbuctoo.tools.importer.JsonImporter  [ vreId [directory] ]
 * </pre>
 */
public class JsonImporter extends CSVImporter {

    private static final Logger LOG = LoggerFactory.getLogger(JsonImporter.class);

    private static final String DEFAULT_VRE_ID = "base";
    private static final String IMPORT_DIRECTORY_NAME = "../../timbuctoo-testdata/src/main/resources/import/";
    private static final String CONTROL_FILE_NAME = "import.txt";

    public static void main(String[] args) throws Exception {
        Stopwatch stopWatch = Stopwatch.createStarted();

        String vreId = (args.length > 0) ? args[0] : DEFAULT_VRE_ID;
        LOG.info("VRE: {}", vreId);

        String directoryName = (args.length > 1) ? args[1] : IMPORT_DIRECTORY_NAME + vreId + "/";
        LOG.info("Import directory: {}", directoryName);

        Injector injector = ToolsInjectionModule.createInjector();
        Repository repository = injector.getInstance(Repository.class);
        IndexManager indexManager = injector.getInstance(IndexManager.class);

        try {
            File directory = new File(directoryName);
            File file = new File(directory, CONTROL_FILE_NAME);
            JsonImporter importer = new JsonImporter(repository, indexManager, vreId, directory);
            importer.handleFile(file, 2, false);
        } finally {
            indexManager.close();
            repository.close();
            LOG.info("Time used: {}", stopWatch);
        }
    }

    // ---------------------------------------------------------------------------

    private final TypeRegistry registry;
    private final File directory;
    private final Handler handler;

    public JsonImporter(Repository repository, IndexManager indexManager, String vreId, File directory) {
        registry = repository.getTypeRegistry();
        this.directory = directory;
        handler = new Handler(repository, indexManager, vreId);
    }

    @Override
    protected void initialize() throws Exception {
        handler.importRelationTypes();
    }

    @Override
    protected void handleLine(String[] items) throws Exception {
        File file = new File(directory, items[0]);
        Class<? extends DomainEntity> type = registry.getDomainEntityType(items[1]);
        handler.handleFile(file, type);
    }

    @Override
    protected void handleEndOfFile() throws Exception {
        handler.indexEntitiesWithRelations();
        handler.displayErrorSummary();
        handler.displayStatus();
    };

    // ---------------------------------------------------------------------------

    private static class Handler extends DefaultImporter {

        /** References of stored primitive entities */
        private final Map<String, Reference> references;
        private final ObjectMapper mapper;

        public Handler(Repository repository, IndexManager indexManager, String vreId) {
            super(repository, indexManager, vreId);
            references = Maps.newHashMap();
            mapper = new ObjectMapper();
        }

        private void storeReference(String key, Class<? extends DomainEntity> type, String id) {
            Reference reference = new Reference(TypeRegistry.toBaseDomainEntity(type), id);
            if (references.put(key, reference) != null) {
                log("Duplicate key '%s'%n", key);
                System.exit(-1);
            }
        }

        public <T extends DomainEntity> void handleFile(File file, Class<T> type) throws Exception {
            printBoxedText("File: " + file.getName());

            // Get rid of existing stuff
            removeNonPersistentEntities(type);

            Progress progress = new Progress();
            LineIterator iterator = Files.getLineIterator(file);
            try {
                while (iterator.hasNext()) {
                    String line = iterator.nextLine().trim();
                    if (!line.isEmpty()) {
                        progress.step();
                        handleEntity(type, line);
                    }
                }
            } finally {
                LineIterator.closeQuietly(iterator);
                progress.done();
            }
        }

        private <T extends DomainEntity> void handleEntity(Class<T> type, String line) throws Exception {
            if (Relation.class.isAssignableFrom(type)) {
                @SuppressWarnings("unchecked")
                Class<? extends Relation> rtype = (Class<? extends Relation>) type;
                handleRelation(rtype, line);
            } else {
                handleNonRelation(type, line);
            }
        }

        // First implementation: expect definition in terms of id's
        private <T extends Relation> void handleRelation(Class<T> type, String line) throws Exception {
            RelationDTO dto = mapper.readValue(line, RelationDTO.class);

            RelationType relationType = repository.getRelationTypeByName(dto.getTypeName(), true);
            Reference typeRef = new Reference(type, relationType.getId());
            Reference sourceRef = resolveEntity(dto.getSourceType(), dto.getSourceKey(), dto.getSourceValue());
            Reference targetRef = resolveEntity(dto.getTargetType(), dto.getTargetKey(), dto.getTargetValue());

            if (typeRef != null && sourceRef != null && targetRef != null) {
                String storedId = addRelation(type, typeRef, sourceRef, targetRef, change, line);
                indexManager.addEntity(type, storedId);
            } else {
                System.err.printf("Error in: %s%n", line);
            }
        }

        private Reference resolveEntity(String iname, String key, String value) {
            return references.get(value);
        }

        private <T extends DomainEntity> void handleNonRelation(Class<T> type, String line) throws Exception {
            //         LOG.info("line={}", line);
            T entity = mapper.readValue(line, type);
            String importId = entity.getId();
            String storedId = addDomainEntity(type, entity);
            if (importId != null) {
                storeReference(importId, type, storedId);
            } else {
                // has no new relations, execute immediately
                indexManager.addEntity(type, storedId);
            }
        }

        private void indexEntitiesWithRelations() throws Exception {
            if (!references.isEmpty()) {
                printBoxedText("Index entities");
                TypeRegistry registry = repository.getTypeRegistry();
                Progress progress = new Progress();
                try {
                    for (Reference reference : references.values()) {
                        progress.step();
                        String iname = reference.getType();
                        Class<? extends DomainEntity> type = registry.getDomainEntityType(iname);
                        indexManager.addEntity(type, reference.getId());
                    }
                } finally {
                    progress.done();
                }
            }
        }
    }

}