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

org.mobicents.gmlc.slee.mlp.MLPResponse Maven / Gradle / Ivy

package org.mobicents.gmlc.slee.mlp;

import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IXMLWriter;
import org.oma.protocols.mlp.svc_result.Pos;

import javax.slee.facilities.Tracer;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by angrygreenfrogs on 3/24/2015.
 * This is a helper for generating MLP XML responses to send to a MLP client.
 * It uses the JiBX generated XML bound classes in org.oma.protocols.mlp
 * It exists to generates consistent XML output using the JiBX marshaller
 * It supports generating a result only for a single MSISDN that has a single Point (X/Y - lat/lon) result
 * In the future, it will likely be replaced by a more complex structure for handling the full variety of MLP
 * results, but I wanted to keep it simple and clear for the first version.
 */
public class MLPResponse {
    public enum MLPResultType {
        OK,
        SYSTEM_FAILURE,
        FORMAT_ERROR,
        UNKNOWN_SUBSCRIBER,
        ABSENT_SUBSCRIBER,
        QOP_NOT_ATTAINABLE,
        POSITION_METHOD_FAILURE,
    }

    /**
     * Logger from the calling SBB
     */
    private Tracer logger;

    public MLPResponse(Tracer logger) {
        this.logger = logger;
    }

    // If there's an internal exception or other error, we have to fallback to some "worst case scenario"
    // static XML return data
    private String genericErrorXML =
            "\n" +
            "  " +
            "  \n" +
            "  \n" +
            "    SYSTEM FAILURE\n" +
            "    Internal IO or parsing error occurred\n" +
            "  \n" +
            "";

    /**
     * Get the MLP result code as per OMA MLP section 5.4.1
     * @param t MLPResultType internal enum value for use in the MLP classes
     * @return MLP result code to return to the client
     */
    public static String getResultCodeForType(MLPResultType t) {
        switch(t) {
            case OK:
                return "0";
            case SYSTEM_FAILURE:
                return "1";
            case UNKNOWN_SUBSCRIBER:
                return "4";
            case ABSENT_SUBSCRIBER:
                return "5";
            case FORMAT_ERROR:
                return "105";
            case QOP_NOT_ATTAINABLE:
                return "201";
            case POSITION_METHOD_FAILURE:
                return "6";
        }

        return "1";
    }

    /**
     * Get the MLP result string as per OMA MLP section 5.4.1
     * @param t MLPResultType internal enum value for use in the MLP classes
     * @return MLP result string to return to the client
     */
    public static String getResultStringForType(MLPResultType t) {
        switch(t) {
            case OK:
                return "OK";
            case SYSTEM_FAILURE:
                return "SYSTEM FAILURE";
            case UNKNOWN_SUBSCRIBER:
                return "UNKNOWN SUBSCRIBER";
            case ABSENT_SUBSCRIBER:
                return "ABSENT SUBSCRIBER";
            case FORMAT_ERROR:
                return "FORMAT ERROR";
            case QOP_NOT_ATTAINABLE:
                return "QOP NOT ATTAINABLE";
            case POSITION_METHOD_FAILURE:
                return "POSITION METHOD FAILURE";
        }

        return "1";
    }

    /**
     * Is this error type a system error?
     * @param t MLPResultType internal enum value for use in the MLP classes
     * @return boolean true if it is a system error
     */
    public static boolean isSystemError(MLPResultType t) {
        switch(t) {
            case SYSTEM_FAILURE:
            case UNKNOWN_SUBSCRIBER:
            case ABSENT_SUBSCRIBER:
            case FORMAT_ERROR:
                return true;
        }

        return false;
    }

    /**
     * Use JiBX marshalling to generate the MLP XML result data for a single successful position look-up
     * @param x X coordinate in WGS84 DMS format
     * @param y Y coordinate in WGS84 DMS format
     * @param radius Position radius in meters (e.g. 5000 for 5km of accuracy)
     * @param msid Location for MSISDN
     * @return String XML result to return to client
     * Example usage:
     *   svcResultXml = MLPResponse.getSinglePositionSuccessXML("27 28 25.00S", "153 01 43.00E", "+1000", "20140507082957", "61307341370");
     * Example result based on above usage:
        
        
        
        
        
        61307341370
        
        
        
        
        
        27 28 25.00S
        153 01 43.00E
        
        
        
        
        
        
        
     */
    public String getSinglePositionSuccessXML(String x, String y, String radius, String msid) {
        // Generate XML response
        String svcResultXml = "";

        try {
            // Eventually this timestamp should be replaced by the actual network position time
            Date requestTime = new Date();
            String date = new SimpleDateFormat("yyyyMMddHHmmss").format(requestTime);
            String utcOffset = new SimpleDateFormat("Z").format(requestTime);

            // Generate the response XML
            svcResultXml = this.generateSinglePositionSuccessXML(x, y, radius, utcOffset, date, msid);
        }
        catch (IllegalArgumentException e) {
            // Generate the error XML
            svcResultXml = this.getSystemErrorResponseXML(MLPResponse.MLPResultType.SYSTEM_FAILURE, "Failed to create request timestamp");
        }
        catch (IOException e) {
            // Generate the error XML
            svcResultXml = this.getSystemErrorResponseXML(MLPResponse.MLPResultType.SYSTEM_FAILURE, "IO failure generating XML");
        }
        catch(org.jibx.runtime.JiBXException e) {
            // Generate the error XML
            svcResultXml = this.getSystemErrorResponseXML(MLPResponse.MLPResultType.SYSTEM_FAILURE, "Failed to generate XML response from internal objects");
        }

        return svcResultXml;
    }

    /**
     * Internal XML generation support function for above getSinglePositionSuccessXML()
     * @param x X coordinate in WGS84 DMS format
     * @param y Y coordinate in WGS84 DMS format
     * @param radius Position radius in meters (e.g. 5000 for 5km of accuracy)
     * @param utcOffSet Utc offset for location timestamp in "[+/-]HHmm" format
     * @param time Location timestamp at above UTC offset in "yyyyMMddHHmmss" format
     * @param msid Location for MSISDN
     * @return String XML result to return to client
     * @throws org.jibx.runtime.JiBXException JiBX had an internal failure of some kind while marshalling the XML
     * @throws IOException IO error occurred while generating the XML result
     */
    private String generateSinglePositionSuccessXML(String x, String y, String radius, String utcOffSet, String time, String msid)
            throws org.jibx.runtime.JiBXException, IOException {
        String lXml = null;
        String ver = "3.1.0";

        // Create all the objects we'll use to generate our svc_result XML
        org.oma.protocols.mlp.svc_result.SvcResult mlpSvcResult = new org.oma.protocols.mlp.svc_result.SvcResult();
        org.oma.protocols.mlp.svc_result.Slia mlpSlia = new org.oma.protocols.mlp.svc_result.Slia();
        org.oma.protocols.mlp.svc_result.Pos mlpPos = new org.oma.protocols.mlp.svc_result.Pos();
        org.oma.protocols.mlp.svc_result.Msid mlpMsid = new org.oma.protocols.mlp.svc_result.Msid();
        org.oma.protocols.mlp.svc_result.Pd mlpPd = new org.oma.protocols.mlp.svc_result.Pd();
        org.oma.protocols.mlp.svc_result.Time mlpTime = new org.oma.protocols.mlp.svc_result.Time();
        org.oma.protocols.mlp.svc_result.Shape mlpShape = new org.oma.protocols.mlp.svc_result.Shape();
        org.oma.protocols.mlp.svc_result.CircularArea mlpCircularArea = new org.oma.protocols.mlp.svc_result.CircularArea();
        org.oma.protocols.mlp.svc_result.Coord mlpCoord = new org.oma.protocols.mlp.svc_result.Coord();
        org.oma.protocols.mlp.svc_result.X mlpX = new org.oma.protocols.mlp.svc_result.X();
        org.oma.protocols.mlp.svc_result.Y mlpY = new org.oma.protocols.mlp.svc_result.Y();
        org.oma.protocols.mlp.svc_result.Radius mlpRadius = new org.oma.protocols.mlp.svc_result.Radius();
        List posList = new ArrayList();

        // Set the key location data
        mlpX.setX(x);
        mlpY.setY(y);
        mlpTime.setUtcOff(utcOffSet);
        mlpMsid.setString(msid);
        mlpRadius.setRadius(radius);

        // Setup all the objects for this single position
        mlpCoord.setX(mlpX);
        mlpCoord.setY(mlpY);
        mlpCircularArea.setCoord(mlpCoord);
        mlpCircularArea.setRadius(mlpRadius);
        mlpShape.setCircularArea(mlpCircularArea);
        mlpPd.setShape(mlpShape);
        mlpTime.setString(time);
        mlpPd.setTime(mlpTime);
        mlpPos.setMsid(mlpMsid);
        mlpPos.setPd(mlpPd);

        // Add it to the position list and result
        posList.add(mlpPos);
        mlpSlia.setPoList(posList);
        mlpSlia.setVer(ver);
        mlpSvcResult.setSlia(mlpSlia);
        mlpSvcResult.setVer(ver);

        lXml = marshalMlpResult(mlpSvcResult);

        // Return our XML string result
        return lXml;
    }

    /**
     * Generate a MLP system error response
     * @param mlpClientErrorType Error type to return to client
     * @param mlpClientErrorMessage Error message to send to client
     * @return String XML result to return to client
     */
    public String getSystemErrorResponseXML(MLPResultType mlpClientErrorType, String mlpClientErrorMessage) {
        // Generate XML response
        String svcResultXml = "";

        try {
            // Generate the error XML
            svcResultXml = this.generateSystemErrorXML(mlpClientErrorType, mlpClientErrorMessage);
            return svcResultXml;
        }
        catch (IOException e) {
            // Return generic XML error response because we couldn't generate the correct response
            e.printStackTrace();
            this.logger.info("Exception while creating XML response data: " + e.getMessage());
            return genericErrorXML;
        }
        catch(org.jibx.runtime.JiBXException e) {
            // Return generic XML error response because we couldn't generate the correct response
            e.printStackTrace();
            this.logger.info("Exception while marshalling XML response data: " + e.getMessage());
            return genericErrorXML;
        }
    }

    /**
     * Internal XML generation support function for above getSystemErrorResponseXML()
     * @param mlpClientErrorType Error type to return to client
     * @param mlpClientErrorMessage Error message to send to client
     * @return String XML result to return to client
     * @throws org.jibx.runtime.JiBXException JiBX had an internal failure of some kind while marshalling the XML
     * @throws IOException IO error occurred while generating the XML result
     */
    private String generateSystemErrorXML(MLPResultType mlpClientErrorType, String mlpClientErrorMessage)
            throws org.jibx.runtime.JiBXException, IOException {
        String lXml = null;
        String ver = "3.1.0";

        // Create all the objects we'll use to generate our svc_result XML
        org.oma.protocols.mlp.svc_result.SvcResult mlpSvcResult = new org.oma.protocols.mlp.svc_result.SvcResult();
        org.oma.protocols.mlp.svc_result.Slia mlpSlia = new org.oma.protocols.mlp.svc_result.Slia();
        org.oma.protocols.mlp.svc_result.Result mlpResult = new org.oma.protocols.mlp.svc_result.Result();
        org.oma.protocols.mlp.svc_result.AddInfo mlpAddInfo = new org.oma.protocols.mlp.svc_result.AddInfo();

        // Set the additional data error message if one is available
        if (mlpClientErrorMessage != null)
        {
            mlpAddInfo.setAddInfo(mlpClientErrorMessage);
            mlpSlia.setAddInfo(mlpAddInfo);
        }

        mlpResult.setString(MLPResponse.getResultStringForType(mlpClientErrorType));
        mlpResult.setResid(MLPResponse.getResultCodeForType(mlpClientErrorType));
        mlpSlia.setResult(mlpResult);
        mlpSlia.setVer(ver);
        mlpSvcResult.setSlia(mlpSlia);
        mlpSvcResult.setVer(ver);

        IBindingFactory jc = BindingDirectory.getFactory(org.oma.protocols.mlp.svc_result.SvcResult.class);
        IMarshallingContext marshaller = jc.createMarshallingContext();
        ByteArrayOutputStream lOutputStream = new ByteArrayOutputStream();
        marshaller.setOutput(lOutputStream, "UTF-8");
        IXMLWriter ix = marshaller.getXmlWriter();

        // Add XML and DOCTYPE headers
        ix.writeXMLDecl("1.0", "UTF-8", null);
        ix.writeDocType("svc_result", "MLP_SVC_RESULT_310.DTD", null, null);

        // Set 4 spaces as the default indenting
        marshaller.setIndent(4);

        // Generate the XML
        marshaller.marshalDocument(mlpSvcResult);

        // Convert the stream to a string
        lXml = new String(lOutputStream.toByteArray(), "UTF-8");

        // Return our XML string result
        return lXml;
    }

    /**
     * Generate a MLP error response for a position
     * @param msid Device MSISDN
     * @param mlpClientErrorType Error type to return to client
     * @param mlpClientErrorMessage Error message to send to client
     * @return String XML result to return to client
     */
    public String getPositionErrorResponseXML(String msid, MLPResultType mlpClientErrorType, String mlpClientErrorMessage) {
        // Generate XML response
        String svcResultXml = "";

        try {
            // Eventually this timestamp should be replaced by the actual network position time
            Date requestTime = new Date();
            String date = new SimpleDateFormat("yyyyMMddHHmmss").format(requestTime);
            String utcOffset = new SimpleDateFormat("Z").format(requestTime);

            // Generate the error XML
            this.logger.info("Creating error XML response for type: "+MLPResponse.getResultCodeForType(mlpClientErrorType)+" message: "+mlpClientErrorMessage);
            svcResultXml = this.generatePositionErrorXML(utcOffset, date, msid, mlpClientErrorType, mlpClientErrorMessage);
            return svcResultXml;
        }
        catch (IllegalArgumentException e) {
            // Return generic XML error response because we couldn't generate the correct response
            e.printStackTrace();
            this.logger.info("Exception while creating timestamp: " + e.getMessage());
            return genericErrorXML;
        }
        catch (IOException e) {
            // Return generic XML error response because we couldn't generate the correct response
            e.printStackTrace();
            this.logger.info("Exception while creating XML response data: " + e.getMessage());
            return genericErrorXML;
        }
        catch(org.jibx.runtime.JiBXException e) {
            // Return generic XML error response because we couldn't generate the correct response
            e.printStackTrace();
            this.logger.info("Exception while marshalling XML response data: " + e.getMessage());
            return genericErrorXML;
        }
    }

    /**
     * Internal XML generation support function for above getSystemErrorResponseXML()
     * @param utcOffSet Utc offset for location timestamp in "[+/-]HHmm" format
     * @param time Location timestamp at above UTC offset in "yyyyMMddHHmmss" format
     * @param msid Device MSISDN
     * @param mlpClientErrorType Error type to return to client
     * @param mlpClientErrorMessage Error message to send to client
     * @return String XML result to return to client
     * @throws org.jibx.runtime.JiBXException JiBX had an internal failure of some kind while marshalling the XML
     * @throws IOException IO error occurred while generating the XML result
     */
    private String generatePositionErrorXML(String utcOffSet, String time, String msid, MLPResultType mlpClientErrorType, String mlpClientErrorMessage)
            throws org.jibx.runtime.JiBXException, IOException {
        String lXml = null;
        String ver = "3.1.0";

        // Create all the objects we'll use to generate our svc_result XML
        org.oma.protocols.mlp.svc_result.SvcResult mlpSvcResult = new org.oma.protocols.mlp.svc_result.SvcResult();
        org.oma.protocols.mlp.svc_result.Slia mlpSlia = new org.oma.protocols.mlp.svc_result.Slia();
        org.oma.protocols.mlp.svc_result.Pos mlpPos = new org.oma.protocols.mlp.svc_result.Pos();
        org.oma.protocols.mlp.svc_result.Msid mlpMsid = new org.oma.protocols.mlp.svc_result.Msid();
        org.oma.protocols.mlp.svc_result.Result mlpResult = new org.oma.protocols.mlp.svc_result.Result();
        org.oma.protocols.mlp.svc_result.AddInfo mlpAddInfo = new org.oma.protocols.mlp.svc_result.AddInfo();
        org.oma.protocols.mlp.svc_result.Poserr mlpPosErr = new org.oma.protocols.mlp.svc_result.Poserr();
        org.oma.protocols.mlp.svc_result.Time mlpTime = new org.oma.protocols.mlp.svc_result.Time();
        List posList = new ArrayList();

        // Set the data
        mlpTime.setUtcOff(utcOffSet);
        mlpTime.setString(time);
        mlpMsid.setString(msid);

        // Set the additional data error message if one is available
        if (mlpClientErrorMessage != null)
        {
            mlpAddInfo.setAddInfo(mlpClientErrorMessage);
            mlpPosErr.setAddInfo(mlpAddInfo);
        }

        mlpResult.setString(MLPResponse.getResultStringForType(mlpClientErrorType));
        mlpResult.setResid(MLPResponse.getResultCodeForType(mlpClientErrorType));
        mlpPosErr.setResult(mlpResult);
        mlpPosErr.setTime(mlpTime);
        mlpPos.setMsid(mlpMsid);
        mlpPos.setPoserr(mlpPosErr);
        posList.add(mlpPos);
        mlpSlia.setPoList(posList);
        mlpSlia.setVer(ver);
        mlpSvcResult.setSlia(mlpSlia);
        mlpSvcResult.setVer(ver);

        lXml = marshalMlpResult(mlpSvcResult);

        // Return our XML string result
        return lXml;
    }

    /**
     * Create the svc_result XML result for any type of result (error or success)
     * @param mlpSvcResult Fully filled in SvcResult object to marshal (convert to XML)
     * @return String of XML result to send to client
     * @throws org.jibx.runtime.JiBXException JiBX had an internal failure of some kind while marshalling the XML
     * @throws IOException IO error occurred while generating the XML result
     */
    private String marshalMlpResult(org.oma.protocols.mlp.svc_result.SvcResult mlpSvcResult)
            throws org.jibx.runtime.JiBXException, IOException {
        String lXml = null;

        IBindingFactory jc = BindingDirectory.getFactory(org.oma.protocols.mlp.svc_result.SvcResult.class);
        IMarshallingContext marshaller = jc.createMarshallingContext();
        ByteArrayOutputStream lOutputStream = new ByteArrayOutputStream();
        marshaller.setOutput(lOutputStream, "UTF-8");
        IXMLWriter ix = marshaller.getXmlWriter();

        // Add XML and DOCTYPE headers
        ix.writeXMLDecl("1.0", "UTF-8", null);
        ix.writeDocType("svc_result", "MLP_SVC_RESULT_310.DTD", null, null);

        // Set 4 spaces as the default indenting
        marshaller.setIndent(4);

        // Generate the XML
        marshaller.marshalDocument(mlpSvcResult);

        // Convert the stream to a string
        lXml = new String(lOutputStream.toByteArray(), "UTF-8");

        // Return our XML string result
        return lXml;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy