Package com.bbn.openmap.layer.rpf

Source Code of com.bbn.openmap.layer.rpf.RpfUtil

//**********************************************************************
//
//<copyright>
//
//BBN Technologies, a Verizon Company
//10 Moulton Street
//Cambridge, MA 02138
//(617) 873-8000
//
//Copyright (C) BBNT Solutions LLC. All rights reserved.
//
//</copyright>
//**********************************************************************
//
//$Source:
///cvs/darwars/ambush/aar/src/com/bbn/ambush/mission/MissionHandler.java,v
//$
//$RCSfile: RpfUtil.java,v $
//$Revision: 1.1.2.3 $
//$Date: 2007/03/12 20:52:00 $
//$Author: dietrick $
//
//**********************************************************************

package com.bbn.openmap.layer.rpf;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import com.bbn.openmap.util.ArgParser;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.FileUtils;

/**
* The RpfUtil is a program that will allow you to manage RPF data
* geographically. You can copy and delete RPF data frames from RPF
* data directories, make an A.TOC file for a RPF directory (even
* after copying and/or deleting), and you can zip an RPF directory
* into an archive if you like. You can limit the commands to only
* affect those frames completely inside or outside a specified area,
* or for those frames that intersect and are contained by that area
* (default). You can also limit the charts affected based on their
* map scales, providing a scale and indicating that you only want
* those frames that match the scale, do not match the scale, are
* greater or less than the scale. Greater than or less than refers to
* the scale number of the chart being greater or less than the scale
* number provided, NOT whether the resuting scale ratio is greater or
* less than. These things are opposite if each other, and we're just
* working with the numbers.
* <p>
*
* When you call RpfUtil.setRpfDir, that calls organizeFrames(rpfDir),
* which creates a list of the frames affected by the scale and
* boundary settings. Then, the operation runs on those frames.
* <p>
*
* It is important that the A.TOC file in the source RPF directory
* reflects the current state of the data in that directory. If you
* are not sure, run this program with the -maketoc option on that
* directory to update it.
*
* @author dietrick
*/
public class RpfUtil {

    public final static char SCALE_EQUALS = 'e';
    public final static char SCALE_NOTEQUALS = 'n';
    public final static char SCALE_GREATERTHAN = 'g';
    public final static char SCALE_LESSTHAN = 'l';
    public final static float ALL_SCALES = 0f;

    public final static int BOUNDED = 0;
    public final static int INSIDE = 1;
    public final static int OUTSIDE = 2;

    protected int boundaryLimits = BOUNDED;
    protected float scale = ALL_SCALES;
    protected char scaleDelim = SCALE_EQUALS;
    protected float upperLat = 90f;
    protected float leftLon = -180;
    protected float lowerLat = -90f;
    protected float rightLon = 180f;
    protected String rpfDir;

    protected boolean verbose = false;

    protected List frameList;

    /**
     * Create a default RpfUtil considering all data.
     */
    public RpfUtil() {}

    /**
     * Create a RpfUtil considering data intersecting the provided
     * boundary. The RPF data directory still needs to be set.
     *
     * @param ulat upper latitude
     * @param llon left longitude
     * @param llat lower latitude
     * @param rlon right longitude
     */
    public RpfUtil(float ulat, float llon, float llat, float rlon) {
        this(null, ulat, llon, llat, rlon, 0f, SCALE_EQUALS, BOUNDED);
    }

    /**
     * Create a RpfUtil considering data intersecting the provided
     * boundary, involving the provided RPF directory.
     *
     * @param rpfDir the RPF directory to search and consider frames
     *        over.
     * @param ulat upper latitude
     * @param llon left longitude
     * @param llat lower latitude
     * @param rlon right longitude
     */
    public RpfUtil(String rpfDir, float ulat, float llon, float llat, float rlon) {
        this(rpfDir, ulat, llon, llat, rlon, 0f, SCALE_EQUALS, BOUNDED);
    }

    /**
     * Full control over the RpfUtil settings.
     *
     * @param rpfDir the RPF directory to search and consider frames
     *        over.
     * @param ulat upper latitude
     * @param llon left longitude
     * @param llat lower latitude
     * @param rlon right longitude
     * @param scale the scale of the charts to consider.
     * @param scaleDelimiter character 'g'reater than, 'l'ess than,
     *        'n'ot equal to, 'e'qual to. e is the default.
     * @param boundaryLimits INSIDE, OUTSIDE or BOUNDARY
     */
    public RpfUtil(String rpfDir, float ulat, float llon, float llat,
            float rlon, float scale, char scaleDelimiter, int boundaryLimits) {
        this.upperLat = ulat;
        this.lowerLat = llat;
        this.leftLon = llon;
        this.rightLon = rlon;
        this.scale = scale;
        this.scaleDelim = scaleDelimiter;
        this.boundaryLimits = boundaryLimits;

        setRpfDir(rpfDir);
    }

    /**
     * Creates the list of frames to consider, based on settings. This
     * method does a cursory check of scale settings before moving to
     * geographical settings.
     *
     * @param rpfDir
     * @return List of relative path names to frames.
     */
    protected List organizeFrames(String rpfDir) {
        RpfTocHandler toc = new RpfTocHandler(rpfDir);
        List frameList = new LinkedList();

        if (toc.isValid()) {
            RpfTocEntry[] entries = toc.getEntries();
            if (verbose) {
                Debug.output("Figuring out which frames fit the criteria...");
            }
            for (int i = 0; i < entries.length; i++) {
                RpfTocEntry entry = entries[i];
                toc.loadFrameInformation(entry);

                double udinterval = (entry.coverage.nw_lat - entry.coverage.se_lat)
                        / entry.vertFrames;
                double rlinterval = (entry.coverage.se_lon - entry.coverage.nw_lon)
                        / entry.horizFrames;

                if (scale > 0) {
                    float rectScale = (float) RpfTocHandler.textScaleToLong(entry.scale);

                    if (rectScale == RpfConstants.UK.scale) {
                        if (verbose) {
                            Debug.output("  RpfTocEntry[" + i
                                    + "] scale unknown ("
                                    + entry.coverage.chartCode + "), skipping");
                        }
                        continue;
                    }

                    switch (scaleDelim) {
                    case SCALE_EQUALS:
                        if (scale == rectScale)
                            frameList.addAll(getFrameList(entry,
                                    rlinterval,
                                    udinterval));
                        break;
                    case SCALE_GREATERTHAN:
                        if (scale >= rectScale)
                            frameList.addAll(getFrameList(entry,
                                    rlinterval,
                                    udinterval));
                        break;
                    case SCALE_LESSTHAN:
                        if (scale <= rectScale)
                            frameList.addAll(getFrameList(entry,
                                    rlinterval,
                                    udinterval));
                        break;
                    case SCALE_NOTEQUALS:
                        if (scale != rectScale)
                            frameList.addAll(getFrameList(entry,
                                    rlinterval,
                                    udinterval));
                    default:
                        break;
                    } // switch

                } else {
                    frameList.addAll(getFrameList(entry, rlinterval, udinterval));
                }

            }
        }

        return frameList;

    }

    /**
     * Middle management for frames for A.TOC entry box.
     *
     * @param entry RpfTocEntry to consider.
     * @param rlinterval right to left decimal degree interval for
     *        entry.
     * @param udinterval up to down decimal degree interval for entry
     * @return List of frames that pass current settings.
     */
    protected List getFrameList(RpfTocEntry entry, double rlinterval,
                                double udinterval) {
        List frameList = new LinkedList();
       
        for (int hor = 0; hor < entry.horizFrames; hor++) {
            for (int ver = 0; ver < entry.vertFrames; ver++) {

                RpfFrameEntry frame = entry.getFrame(ver, hor);

                double left = entry.coverage.nw_lon + (rlinterval * hor);
                double right = left + rlinterval;
                double up = entry.coverage.nw_lat - (udinterval * ver);
                double down = up - udinterval;

                if (frame.exists
                        && frameFitsCriteria(left,
                                right,
                                up,
                                down,
                                rlinterval,
                                udinterval)) {
                    String name = frame.framePath.substring(frame.rpfdirIndex + 3);

                    frameList.add(name);

                    if (verbose) {
                        Debug.output(" getFrameList: adding file " + name);
                    }
                }

            }
        }

        return frameList;
    }

    /**
     * Geographical evaluation of frame file
     *
     * @return true if file should be added to the list.
     */
    protected boolean frameFitsCriteria(double left, double right, double up,
                                        double down, double rlinterval,
                                        double udinterval) {

        switch (boundaryLimits) {
        case OUTSIDE:
            return (left < leftLon && right < leftLon)
                    || (left > rightLon && right > rightLon)
                    || (up < lowerLat && down < lowerLat)
                    || (up > upperLat && down > upperLat);
        case INSIDE:
            return (left > leftLon && right > leftLon && left < rightLon
                    && right < rightLon && up > lowerLat && down > lowerLat
                    && up < upperLat && down < upperLat);
        default:
            return (((right <= rightLon && left >= leftLon - rlinterval)
                    || (left >= leftLon && right <= rightLon + rlinterval) || (left <= leftLon && right >= rightLon)) && ((up <= upperLat
                    + udinterval && down >= lowerLat)
                    || (down >= lowerLat - udinterval && up <= upperLat) || (up >= upperLat && down <= lowerLat)));
        }
    }

    /**
     * Copy the frame files currently set on the FrameList to the
     * provided RPF directory.
     *
     * @param toRpfDir
     * @return true if it works.
     */
    public boolean copy(String toRpfDir) {
        File toDir = new File(toRpfDir);
        boolean ret = false;
        String sourceRpfDir = getRpfDir();
        if ((toDir.exists() || toDir.mkdirs()) && frameList != null) {
            if (verbose) {
                Debug.output("From " + sourceRpfDir + " to " + toRpfDir + ":");
            }
            for (Iterator it = frameList.iterator(); it.hasNext();) {
                String relativeFilePath = "/" + (String) it.next();
                File fromFile = new File(sourceRpfDir + relativeFilePath);
                File toFile = new File(toRpfDir + relativeFilePath);
                File toParent = toFile.getParentFile();
                if (!toParent.exists()) {
                    toParent.mkdirs();
                }
                if (verbose) {
                    Debug.output("Copying " + relativeFilePath);
                }

                try {
                    FileUtils.copy(fromFile, toFile, 400000);
                } catch (IOException ioe) {
                    Debug.error("RpfUtil.copy:  IOExeption copying files: "
                            + ioe.getMessage());
                    return false;
                }
            }
            ret = true;
        }

        return ret;
    }

    /**
     * Create an A.TOC file for the provided RPF directory.
     *
     * @param rpfDir
     * @return true if it works.
     */
    public boolean maketoc(String rpfDir) {
        boolean ret = false;

        MakeToc mt = new MakeToc();
        String[] paths = new String[] { rpfDir };

        // paths is going to be reset to list all of the RPF frame
        // file paths.
        paths = mt.searchForRpfFiles(paths);

        try {
            mt.create(paths,
                    rpfDir + "/" + RpfTocHandler.RPF_TOC_FILE_NAME,
                    false);
            ret = true;
        } catch (MakeTocException mte) {
            Debug.error("Problem creating A.TOC file: \n" + mte.getMessage());
        }

        return ret;
    }

    /**
     * Delete the files in the provided RPF directory that match the
     * current scale and boundary settings.
     *
     * @param rpfDir
     * @return true if it works.
     */
    public boolean delete(String rpfDir) {
        boolean ret = false;

        List frameList = organizeFrames(rpfDir);
        if (frameList != null) {
            for (Iterator it = frameList.iterator(); it.hasNext();) {
                String relativeFilePath = "/" + (String) it.next();
                File fromFile = new File(rpfDir + relativeFilePath);
                if (fromFile.exists() && fromFile.delete() && verbose) {
                    Debug.output("Deleting " + fromFile.getPath());
                }
            }
            ret = true;
        }

        return ret;
    }

    /**
     * Store the contents of the toBeZippedName directory into a zip
     * file with the provided name. If the zip file name doesn't end
     * in .zip, it will.
     *
     * @param zipLocation
     * @param toBeZippedName
     * @return true if it works.
     */
    public boolean zip(String zipLocation, String toBeZippedName) {
        boolean ret = false;

        if (verbose)
            Debug.put("zip");

        File toBeZipped = new File(toBeZippedName);
        if (toBeZipped.exists()) {
            try {
                FileUtils.saveZipFile(zipLocation, toBeZipped);
                ret = true;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return ret;
    }

    /**
     * Just run a query on the provided directory, listing the names
     * of the frames that will be affected by the current scale and
     * boundary settings.
     *
     * @param rpfDir
     */
    public void query(String rpfDir) {
        List frameList = organizeFrames(rpfDir);
        if (frameList != null) {
            for (Iterator it = frameList.iterator(); it.hasNext();) {
                Debug.output(it.next().toString());
            }
        }
    }

    /**
     * The RpfUtil class can be run as a java program. This program
     * will allow commands to be stacked, but will execute them in
     * this order - copy, delete, maketoc, zip. Only one version of
     * each argument is allowed per execution.
     *
     * @param args
     */
    public static void main(String[] args) {
        Debug.init();
        ArgParser ap = new ArgParser("RpfUtil");
        ap.add("copy",
                "Copy RPF data from one RPF directory to another. (-copy from to)",
                2);
        ap.add("delete",
                "Delete RPF data from a RPF directory. (-delete from)",
                1);
        ap.add("maketoc",
                "Create an A.TOC file in a RPF directory. (-maketoc from).",
                1);
        ap.add("zip",
                "Create a zip file from a RPF directory. (-zip zipFileName from)",
                2);
        ap.add("query",
                "Print the paths of files that fit the criteria, but do nothing",
                1);
        ap.add("scale",
                "The scale to use for criteria in matching chart types, followed by a letter describing the relationship of matching frame scales to give scale ('g'reater than, 'l'ess than, 'n'ot equal to, 'e'qual to). (optional)",
                2);
        ap.add("boundary",
                "Coordinates of bounding box (upper lat, left lon, lower lat, right lon) (optional)",
                4,
                true);
        ap.add("inside",
                "Flag to manage RPF frames inside bounding box. (default, optional)");
        ap.add("outside",
                "Flag to manage RPF frames outside bounding box. (optional)");
        ap.add("verbose", "Print out progress");
        ap.add("extraverbose", "Print out ALL progress");

        if (!ap.parse(args)) {
            ap.printUsage();
            System.exit(0);
        }

        float ulat = 90f;
        float llat = -90f;
        float llon = -180f;
        float rlon = 180f;

        String arg[];
        arg = ap.getArgValues("boundary");
        if (arg != null) {
            boolean boundaryCoordinateProblem = true;
            try {
                ulat = Float.parseFloat(arg[0]);
                llon = Float.parseFloat(arg[1]);
                llat = Float.parseFloat(arg[2]);
                rlon = Float.parseFloat(arg[3]);

                boundaryCoordinateProblem = ulat > 90 || llon < -180
                        || llat < -90 || rlon > 180 || ulat <= llat
                        || llon >= rlon;

            } catch (NumberFormatException nfe) {
                Debug.error("Parsing error for boundary coordinates");
            }

            if (boundaryCoordinateProblem) {
                Debug.error("Boundary coordinates are screwy...");
                ap.printUsage();
                System.exit(0);
            }
        }

        RpfUtil rpfUtil = new RpfUtil(ulat, llon, llat, rlon);

        rpfUtil.verbose = (ap.getArgValues("verbose") != null);

        arg = ap.getArgValues("outside");
        if (arg != null) {
            rpfUtil.setBoundaryLimits(RpfUtil.OUTSIDE);
        }

        arg = ap.getArgValues("inside");
        if (arg != null) {
            rpfUtil.setBoundaryLimits(RpfUtil.INSIDE);
        }

        arg = ap.getArgValues("scale");
        if (arg != null) {
            try {
                rpfUtil.setScale(Float.parseFloat(arg[0]));
                rpfUtil.setScaleDelim(arg[1].charAt(0));
            } catch (NumberFormatException nfe) {
                Debug.error("Scale value is screwy...");
                ap.printUsage();
                System.exit(0);
            }
        }

        arg = ap.getArgValues("query");
        if (arg != null) {
            rpfUtil.query(arg[0]);
            System.exit(0);
        }

        arg = ap.getArgValues("copy");
        if (arg != null) {
            rpfUtil.setRpfDir(arg[0]);
            if (!rpfUtil.copy(arg[1])) {
                Debug.output("Problem copying frames");
            }
        }

        arg = ap.getArgValues("delete");
        if (arg != null && !rpfUtil.delete(arg[0])) {
            Debug.output("Problem deleting files.");
        }

        arg = ap.getArgValues("maketoc");
        if (arg != null && !rpfUtil.maketoc(arg[0])) {
            Debug.output("Problem creating A.TOC file for frames.");
        }

        arg = ap.getArgValues("zip");
        if (arg != null && !rpfUtil.zip(arg[0], arg[1])) {
            Debug.output("Problem creating zip file: " + arg[0]);
        }
    }

    public int getBoundaryLimits() {
        return boundaryLimits;
    }

    /**
     * Set whether the frames need to be INSIDE, OUTSIDE or inside and
     * touching the BOUNDARY of the geographical area set in the
     * RpfUtil object.
     *
     * @param boundaryLimits
     */
    public void setBoundaryLimits(int boundaryLimits) {
        this.boundaryLimits = boundaryLimits;
    }

    public List getFrameList() {
        return frameList;
    }

    public void setFrameList(List frameList) {
        this.frameList = frameList;
    }

    public float getLeftLon() {
        return leftLon;
    }

    public void setLeftLon(float leftLon) {
        this.leftLon = leftLon;
    }

    public float getLowerLat() {
        return lowerLat;
    }

    public void setLowerLat(float lowerLat) {
        this.lowerLat = lowerLat;
    }

    public float getRightLon() {
        return rightLon;
    }

    public void setRightLon(float rightLon) {
        this.rightLon = rightLon;
    }

    public String getRpfDir() {
        return rpfDir;
    }

    /**
     * Creates the list of frames matching the geographical and scale
     * parameters of the frames within the directory.
     *
     * @param rpfDir
     */
    public void setRpfDir(String rpfDir) {
        this.rpfDir = rpfDir;
        if (rpfDir != null) {
            frameList = organizeFrames(rpfDir);
        }
    }

    public float getScale() {
        return scale;
    }

    public void setScale(float scale) {
        this.scale = scale;
    }

    public char getScaleDelim() {
        return scaleDelim;
    }

    /**
     * Set whether the frames considered should have scale numbers
     * greater than (g), less than (l), not equal to (n) or equal to
     * (e). Equal to is the default, and that's set if any other value
     * os provided.
     *
     * @param scaleDelim
     */
    public void setScaleDelim(char scaleDelim) {
        if (scaleDelim == SCALE_NOTEQUALS || scaleDelim == SCALE_GREATERTHAN
                || scaleDelim == SCALE_LESSTHAN) {
            this.scaleDelim = scaleDelim;
        } else {
            this.scaleDelim = SCALE_EQUALS;
        }
    }

    public float getUpperLat() {
        return upperLat;
    }

    public void setUpperLat(float upperLat) {
        this.upperLat = upperLat;
    }

}
TOP

Related Classes of com.bbn.openmap.layer.rpf.RpfUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.