org.codice.alliance.transformer.nitf.gmti.NitfGmtiTransformer.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.alliance.transformer.nitf.gmti.NitfGmtiTransformer.java

Source

/**
 * Copyright (c) Codice Foundation
 * <p/>
 * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or any later version.
 * <p/>
 * 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
 * Lesser General Public License for more details. A copy of the GNU Lesser General Public License
 * is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.alliance.transformer.nitf.gmti;

import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.codice.alliance.catalog.core.api.types.Isr;
import org.codice.alliance.transformer.nitf.common.SegmentHandler;
import org.codice.imaging.nitf.core.common.NitfFormatException;
import org.codice.imaging.nitf.core.common.TaggedRecordExtensionHandler;
import org.codice.imaging.nitf.core.tre.Tre;
import org.codice.imaging.nitf.core.tre.TreGroup;
import org.codice.imaging.nitf.fluent.NitfSegmentsFlow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

import ddf.catalog.data.Attribute;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.impl.AttributeImpl;
import ddf.catalog.data.types.Core;
import ddf.catalog.transform.CatalogTransformerException;

public class NitfGmtiTransformer extends SegmentHandler {

    private static final String ACFTB = "ACFTB";

    private static final String MTIRPB = "MTIRPB";

    private static final String TARGETS = "TARGETS";

    private static final Logger LOGGER = LoggerFactory.getLogger(NitfGmtiTransformer.class);

    // Handles locations that have either 6 or 7 decimal places
    private static final String LOCATION_REGEX = "([+\\-]\\d{2}+\\.\\d{6,7}+)([+\\-]\\d{3}+\\.\\d{6,7})";

    private static final Pattern LOCATION_PATTERN = Pattern.compile(LOCATION_REGEX);

    private GeometryFactory geometryFactory;

    public Metacard transform(NitfSegmentsFlow nitfSegmentsFlow, Metacard metacard)
            throws IOException, CatalogTransformerException {

        if (nitfSegmentsFlow == null) {
            throw new IllegalArgumentException("argument 'nitfSegmentsFlow' may not be null.");
        }

        if (metacard == null) {
            throw new IllegalArgumentException("argument 'metacard' may not be null.");
        }

        nitfSegmentsFlow.fileHeader(header -> handleHeader(header, metacard)).end();

        transformTargetLocation(metacard);
        transformAircraftLocation(metacard);

        return metacard;
    }

    private void handleHeader(TaggedRecordExtensionHandler header, Metacard metacard) {
        List<Tre> tres = header.getTREsRawStructure().getTREs();

        tres.stream().filter(tre -> ACFTB.equals(tre.getName().trim()))
                .forEach(tre -> handleSegmentHeader(metacard, tre, AcftbAttribute.values()));

        tres.stream().filter(tre -> MTIRPB.equals(tre.getName().trim())).forEach(tre -> {
            handleSegmentHeader(metacard, tre, MtirpbAttribute.values());

            try {
                List<TreGroup> targets = tre.getEntry(TARGETS).getGroups();

                targets.stream()
                        .forEach(group -> handleSegmentHeader(metacard, group, IndexedMtirpbAttribute.values()));
            } catch (NitfFormatException e) {
                LOGGER.warn("Could not parse NITF target information: " + e.getMessage(), e);
            }
        });
    }

    private void transformTargetLocation(Metacard metacard) {
        String locationString = formatTargetLocation(metacard);

        try {
            LOGGER.debug("Formatted Target Location(s) = " + locationString);

            if (locationString != null) {
                // validate the wkt
                WKTReader wktReader = new WKTReader(geometryFactory);
                Geometry geometry = wktReader.read(locationString);

                LOGGER.debug("Setting the metacard attribute [{}, {}]", Core.LOCATION, geometry.toText());
                metacard.setAttribute(new AttributeImpl(Core.LOCATION, geometry.toText()));
            }

        } catch (ParseException e) {
            LOGGER.warn(e.getMessage(), e);
        }
    }

    private String formatTargetLocation(Metacard metacard) {
        Attribute locationAttribute = metacard
                .getAttribute(IndexedMtirpbAttribute.INDEXED_TARGET_LOCATION.getAttributeDescriptor().getName());

        if (locationAttribute != null) {
            StringBuilder stringBuilder = new StringBuilder("MULTIPOINT (");

            locationAttribute.getValues().stream().forEach(value -> {
                parseLocation(stringBuilder, value.toString());
                stringBuilder.append(",");
            });

            stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(","));
            stringBuilder.append(")");
            return stringBuilder.toString();
        }

        return null;
    }

    private void transformAircraftLocation(Metacard metacard) {

        String aircraftLocation = formatAircraftLocation(metacard);

        try {
            LOGGER.debug("Formatted Aircraft Location = " + aircraftLocation);

            if (aircraftLocation != null) {
                // validate the wkt
                WKTReader wktReader = new WKTReader(geometryFactory);
                Geometry geometry = wktReader.read(aircraftLocation);

                LOGGER.debug("Setting the metacard attribute [{}, {}]", Isr.DWELL_LOCATION, aircraftLocation);
                metacard.setAttribute(new AttributeImpl(Isr.DWELL_LOCATION, aircraftLocation));
            }

        } catch (ParseException e) {
            LOGGER.warn(e.getMessage(), e);
        }
    }

    private String formatAircraftLocation(Metacard metacard) {
        Attribute aircraftLocation = metacard
                .getAttribute(MtirpbAttribute.AIRCRAFT_LOCATION.getAttributeDescriptor().getName());

        if (aircraftLocation != null && StringUtils.isNotEmpty(aircraftLocation.getValue().toString())) {

            String unformattedAircraftLocation = aircraftLocation.getValue().toString();

            StringBuilder sb = new StringBuilder("POINT (");
            parseLocation(sb, unformattedAircraftLocation);
            sb.append(")");

            return sb.toString();
        }

        return null;
    }

    private void parseLocation(StringBuilder stringBuilder, String locationString) {

        if (StringUtils.isEmpty(locationString)) {
            return;
        }

        Matcher matcher = LOCATION_PATTERN.matcher(locationString);

        if (matcher.matches()) {
            String lon = matcher.group(1);
            String lat = matcher.group(2);

            stringBuilder.append(String.format("%s %s", lon, lat));
        }
    }

    public void setGeometryFactory(GeometryFactory geometryFactory) {
        this.geometryFactory = geometryFactory;
    }
}