package mil.nga.giat.geowave.format.stanag4676.parser; import java.io.BufferedWriter; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.TimeZone; import mil.nga.giat.geowave.format.stanag4676.parser.model.Area; import mil.nga.giat.geowave.format.stanag4676.parser.model.ClassificationCredibility; import mil.nga.giat.geowave.format.stanag4676.parser.model.ClassificationLevel; import mil.nga.giat.geowave.format.stanag4676.parser.model.CovarianceMatrix; import mil.nga.giat.geowave.format.stanag4676.parser.model.ExerciseIndicator; import mil.nga.giat.geowave.format.stanag4676.parser.model.GeodeticPosition; import mil.nga.giat.geowave.format.stanag4676.parser.model.IDdata; import mil.nga.giat.geowave.format.stanag4676.parser.model.MissionFrame; import mil.nga.giat.geowave.format.stanag4676.parser.model.MissionSummary; import mil.nga.giat.geowave.format.stanag4676.parser.model.MissionSummaryMessage; import mil.nga.giat.geowave.format.stanag4676.parser.model.ModalityType; import mil.nga.giat.geowave.format.stanag4676.parser.model.MotionImagery; import mil.nga.giat.geowave.format.stanag4676.parser.model.NATO4676Message; import mil.nga.giat.geowave.format.stanag4676.parser.model.ObjectClassification; import mil.nga.giat.geowave.format.stanag4676.parser.model.Security; import mil.nga.giat.geowave.format.stanag4676.parser.model.SimulationIndicator; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackClassification; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackEvent; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackIdentity; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackManagement; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackMessage; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackPoint; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackPointDetail; import mil.nga.giat.geowave.format.stanag4676.parser.model.TrackRun; public class NATO4676Encoder implements TrackEncoder { private static final Charset UTF_8 = Charset.forName("UTF-8"); private final ExerciseIndicator defaultExerciseIndicator; private final Security defaultSecurity; private SimulationIndicator defaultSimulationIndicator; private int indentLevel = 0; private final String stanagVersion; private PrintWriter pw = null; private OutputStream trackOut = null; private OutputStream missionOut = null; private PrintWriter pwTrack = null; private PrintWriter pwMission = null; private String indent() { if (indentLevel == 0) { return ""; } final char[] indention = new char[indentLevel]; Arrays.fill( indention, '\t'); return new String( indention); } public void setDefaultSecurityLevel( final String level ) { defaultSecurity.setClassification(ClassificationLevel.valueOf(level)); } public void setDefaultSimulationString( final String simString ) { defaultSimulationIndicator = SimulationIndicator.valueOf(simString); } public NATO4676Encoder() { defaultSecurity = new Security(); defaultSecurity.setClassification(ClassificationLevel.UNCLASSIFIED); defaultSecurity.setPolicyName("NATO"); defaultExerciseIndicator = ExerciseIndicator.OPERATIONAL; stanagVersion = "1.0"; } @Override public void setOutputStreams( final OutputStream trackOut, final OutputStream missionOut ) { this.trackOut = trackOut; this.missionOut = missionOut; final OutputStreamWriter trackOsw = new OutputStreamWriter( this.trackOut, UTF_8); final OutputStreamWriter missionOsw = new OutputStreamWriter( this.missionOut, UTF_8); pwTrack = new PrintWriter( new BufferedWriter( trackOsw, 8192)); pw = pwTrack; pwMission = new PrintWriter( new BufferedWriter( missionOsw, 8192)); } private String GetXMLOpen() { return "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; } private String GetXMLClose() { return ""; } /** * A TrackRun will be encoded as a single NATO4676Message even though there * may be multiple messages inside it. The LAST NATO4676Message should be * used. * * * @param run * @return */ @Override public void Encode( final TrackRun run ) { boolean firstTrackMessage = true; boolean trackMessagesExist = false; for (final NATO4676Message msg : run.getMessages()) { indentLevel = 0; if (msg instanceof TrackMessage) { TrackMessage trackMsg = (TrackMessage) msg; if (firstTrackMessage) { pw.write(GetXMLOpen()); pw .write("<TrackMessage xmlns=\"urn:int:nato:stanag4676:0.14\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" schemaVersion=\"0.14\">\n"); indentLevel++; EncodeMsgMetadata(msg); indentLevel--; firstTrackMessage = false; trackMessagesExist = true; } Encode(trackMsg); } else if (msg instanceof MissionSummaryMessage) { pw = pwMission; MissionSummaryMessage msMsg = (MissionSummaryMessage) msg; MissionSummary ms = msMsg.getMissionSummary(); if (ms != null) { pw.write(GetXMLOpen()); pw .write("<MissionSummary xmlns=\"http://siginnovations.com/MissionSummarySIG\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"); indentLevel++; EncodeMsgMetadata(msg); pw.write(indent() + "<Name>" + ms.getName() + "</Name>\n"); pw.write(indent() + "<missionID>" + ms.getMissionId() + "</missionID>\n"); pw.write(indent() + "<StartTime>" + EncodeTime(ms.getStartTime()) + "</StartTime>\n"); pw.write(indent() + "<EndTime>" + EncodeTime(ms.getEndTime()) + "</EndTime>\n"); Area area = ms.getCoverageArea(); if (area != null) { pw.write(indent() + "<CoverageArea xsi:type=\"PolygonArea\">\n"); Encode(area); pw.write(indent() + "</CoverageArea>\n"); } if (ms.getClassifications().size() > 0) { pw.write(indent() + "<ActiveObjectClassifications>\n"); indentLevel++; for (ObjectClassification oc : ms.getClassifications()) { pw.write(indent() + "<classification>" + oc.name() + "</classification>\n"); } indentLevel--; pw.write(indent() + "</ActiveObjectClassifications>\n"); } indentLevel--; Encode(msMsg); pw.write("</MissionSummary>\n"); pw.flush(); pw = pwTrack; } } } if (trackMessagesExist) { pw.write("</TrackMessage>\n"); pw.flush(); } } private void Encode( final TrackMessage msg ) { indentLevel++; for (final TrackEvent trackevent : msg.getTracks()) { pw.write(indent() + "<tracks>\n"); Encode(trackevent); pw.write(indent() + "</tracks>\n"); } indentLevel--; } private void Encode( final MissionSummaryMessage msg ) { indentLevel++; for (final MissionFrame frame : msg.getMissionSummary().getFrames()) { pw.write(indent() + "<FrameInformation>\n"); Encode(frame); pw.write(indent() + "</FrameInformation>\n"); } indentLevel--; } private void EncodeMsgMetadata( final NATO4676Message msg ) { pw.write(indent() + "<stanagVersion>" + stanagVersion + "</stanagVersion>\n"); pw.write(indent() + "<messageSecurity>\n"); Encode(msg.getSecurity()); pw.write(indent() + "</messageSecurity>\n"); pw.write(indent() + "<msgCreatedTime>" + EncodeTime(msg.getMessageTime()) + "</msgCreatedTime>\n"); pw.write(indent() + "<senderId>\n"); Encode(msg.getSenderID()); pw.write(indent() + "</senderId>\n"); } private void Encode( Security sec ) { if (sec == null) { sec = defaultSecurity; } indentLevel++; pw.write(indent() + "<securityClassification>" + sec.getClassification() + "</securityClassification>\n"); pw.write(indent() + "<securityPolicyName>" + sec.getPolicyName() + "</securityPolicyName>\n"); if (sec.getControlSystem() != null) { pw.write(indent() + "<securityControlSystem>" + sec.getControlSystem() + "</securityControlSystem>\n"); } if (sec.getDissemination() != null) { pw.write(indent() + "<securityDissemination>" + sec.getDissemination() + "</securityDissemination>\n"); } if (sec.getReleasability() != null) { pw.write(indent() + "<securityReleasability>" + sec.getReleasability() + "</securityReleasability>\n"); } indentLevel--; } private void Encode( final IDdata id ) { indentLevel++; pw.write(indent() + "<stationID>" + id.getStationId() + "</stationID>\n"); pw.write(indent() + "<nationality>" + id.getNationality() + "</nationality>\n"); indentLevel--; } private void Encode( final TrackEvent event ) { indentLevel++; pw.write(indent() + "<trackUUID>" + event.getUuid() + "</trackUUID>\n"); pw.write(indent() + "<trackNumber>" + event.getTrackNumber() + "</trackNumber>\n"); if (event.getStatus() != null) { pw.write(indent() + "<trackStatus>" + event.getStatus() + "</trackStatus>\n"); } pw.write(indent() + "<trackSecurity>\n"); Encode(event.getSecurity()); pw.write(indent() + "</trackSecurity>\n"); if (event.getComment() != null) { pw.write(indent() + "<trackComment>" + event.getComment() + "</trackComment>\n"); } if (event.getMissionId() != null) { pw.write(indent() + "<missionID>" + event.getMissionId() + "</missionID>\n"); } if (event.getExerciseIndicator() != null) { pw.write(indent() + "<exerciseIndicator>" + event.getExerciseIndicator() + "</exerciseIndicator>\n"); } else { pw.write(indent() + "<exerciseIndicator>" + defaultExerciseIndicator + "</exerciseIndicator>\n"); } if (event.getSimulationIndicator() != null) { pw.write(indent() + "<simulationIndicator>" + event.getSimulationIndicator() + "</simulationIndicator>\n"); } else { pw.write(indent() + "<simulationIndicator>" + defaultSimulationIndicator + "</simulationIndicator>\n"); } for (final TrackPoint point : event.getPoints().values()) { pw.write(indent() + "<items xsi:type=\"TrackPoint\">\n"); Encode(point); pw.write(indent() + "</items>\n"); } for (final TrackIdentity identity : event.getIdentities()) { pw.write(indent() + "<items xsi:type=\"TrackIdentityInformation\">\n"); Encode(identity); pw.write(indent() + "</items>\n"); } for (final TrackClassification tc : event.getClassifications()) { pw.write(indent() + "<items xsi:type=\"TrackClassificationInformation\">\n"); Encode(tc); pw.write(indent() + "</items>\n"); } for (final TrackManagement management : event.getManagements()) { pw.write(indent() + "<items xsi:type=\"TrackManagementInformation\">\n"); Encode(management); pw.write(indent() + "</items>\n"); } for (final MotionImagery image : event.getMotionImages()) { pw.write(indent() + "<items xsi:type=\"MotionImageryInformation\">\n"); Encode(image); pw.write(indent() + "</items>\n"); } // TODO: ESMInformation // TODO: TrackLineageInformation indentLevel--; } private void Encode( final TrackPoint point ) { indentLevel++; pw.write(indent() + "<trackItemUUID>" + point.getUuid() + "</trackItemUUID>\n"); pw.write(indent() + "<trackItemSecurity>\n"); Encode(point.getSecurity()); pw.write(indent() + "</trackItemSecurity>\n"); pw.write(indent() + "<trackItemTime>\n"); pw.write(EncodeTime(point.getEventTime())); pw.write(indent() + "</trackItemTime>\n"); if (point.getTrackItemSource() != null) { pw.write(indent() + "<trackItemSource>" + point.getTrackItemSource() + "</trackItemSource>\n"); } if (point.getTrackItemComment() != null) { pw.write(indent() + "<trackItemComment>" + point.getTrackItemComment() + "</trackItemComment>\n"); } pw.write(indent() + "<trackPointPosition>\n"); Encode(point.getLocation()); pw.write(indent() + "</trackPointPosition>\n"); if (point.getSpeed() != null) { pw.write(indent() + "<trackPointSpeed>" + point.getSpeed().intValue() + "</trackPointSpeed>\n"); } if (point.getCourse() != null) { pw.write(indent() + "<trackPointCourse>" + point.getCourse() + "</trackPointCourse>\n"); } if (point.getTrackPointType() != null) { pw.write(indent() + "<trackPointType>" + point.getTrackPointType() + "</trackPointType>\n"); } if (point.getTrackPointSource() != null) { pw.write(indent() + "<trackPointSource>" + point.getTrackPointSource() + "</trackPointSource>\n"); } // TODO: need objectMask here if (point.getDetail() != null) { pw.write(indent() + "<TrackPointDetail>\n"); Encode(point.getDetail()); pw.write(indent() + "</TrackPointDetail>\n"); } indentLevel--; } private void Encode( final MissionFrame frame ) { indentLevel++; pw.write(indent() + "<frameNumber>" + frame.getFrameNumber() + "</frameNumber>\n"); pw.write(indent() + "<frameTimestamp>" + EncodeTime(frame.getFrameTime()) + "</frameTimestamp>\n"); Area area = frame.getCoverageArea(); if (area != null) { pw.write(indent() + "<frameCoverageArea xsi:type=\"PolygonArea\">\n"); Encode(frame.getCoverageArea()); pw.write(indent() + "</frameCoverageArea>\n"); } pw.write(indent() + "<hasFault>false</hasFault>\n"); indentLevel--; } private void Encode( final TrackIdentity identity ) { // TODO: Encode TrackIdentity } private void Encode( final TrackClassification tc ) { indentLevel++; pw.write(indent() + "<trackItemUUID>" + tc.getUuid() + "</trackItemUUID>\n"); pw.write(indent() + "<trackItemSecurity>\n"); Encode(tc.getSecurity()); pw.write(indent() + "</trackItemSecurity>\n"); pw.write(indent() + "<trackItemTime>" + EncodeTime(tc.getTime()) + "</trackItemTime>\n"); pw.write(indent() + "<numberofObjects>" + tc.getNumObjects() + "</numberofObjects>\n"); ObjectClassification oc = tc.getClassification(); if (oc != null) { pw.write(indent() + "<classification>" + oc.name() + "</classification>\n"); ModalityType mt = ModalityType.fromString(tc.getSource()); if (mt != null) { pw.write(indent() + "<classificationSource>" + mt.toString() + "</classificationSource>\n"); } } ClassificationCredibility cred = tc.getCredibility(); if (cred != null) { pw.write(indent() + "<classificationCredibility>\n"); indentLevel++; pw.write(indent() + "<valueConfidence>" + cred.getValueConfidence() + "</valueConfidence>\n"); pw.write(indent() + "<sourceReliability>" + cred.getSourceReliability() + "</sourceReliability>\n"); indentLevel--; pw.write(indent() + "</classificationCredibility>\n"); } indentLevel--; } private void Encode( final TrackManagement management ) { // TODO: Encode TrackManagement } private void Encode( final MotionImagery image ) { pw.write("\n"); indentLevel++; if (image.getBand() != null) { pw.write(indent() + "<band>" + image.getBand().toString() + "</band>\n"); } if (image.getImageReference() != null) { pw.write(indent() + "<imageReference>" + image.getImageReference() + "</imageReference>\n"); } if (image.getImageChip() != null) { pw.write(indent() + "<imageChip>\n"); EncodeImage(image.getImageChip()); pw.write(indent() + "</imageChip>\n"); } indentLevel--; } private void EncodeImage( final String base64imageChip ) { indentLevel++; pw.write(indent() + "<![CDATA[" + base64imageChip + "]]>\n"); indentLevel--; } private String EncodeTime( final Long time ) { // change long to 2011-08-24T18:05:30.375Z format final SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); final String xml = sdf.format(new Date( time)); return xml; } private void Encode( final GeodeticPosition pos ) { indentLevel++; pw.write(indent() + "<latitude>" + pos.latitude + "</latitude>\n"); pw.write(indent() + "<longitude>" + pos.longitude + "</longitude>\n"); if (pos.elevation != null) { pw.write(indent() + "<elevation>" + pos.elevation + "</elevation>\n"); } indentLevel--; } private void Encode( final Area coverageArea ) { indentLevel++; if (coverageArea != null) { for (GeodeticPosition pos : coverageArea.getPoints()) { pw.write(indent() + "<areaBoundaryPoints xsi:type=\"GeodeticPosition\">\n"); Encode(pos); pw.write(indent() + "</areaBoundaryPoints>\n"); } } indentLevel--; } private void Encode( final TrackPointDetail detail ) { indentLevel++; pw.write(indent() + "<pointDetailPosition xsi:type=\"GeodeticPosition\">\n"); Encode(detail.getLocation()); pw.write(indent() + "</pointDetailPosition>\n"); if ((detail.getVelocityX() != null) || (detail.getVelocityY() != null) || (detail.getVelocityZ() != null)) { pw.write(indent() + "<pointDetailVelocity xsi:type=\"LocalCartesianVelocity\">\n"); indentLevel++; if (detail.getVelocityX() != null) { pw.write(indent() + "<velx>" + detail.getVelocityX() + "</velx>\n"); } else { pw.write(indent() + "<velx>0</velx>\n"); } if (detail.getVelocityY() != null) { pw.write(indent() + "<vely>" + detail.getVelocityY() + "</vely>\n"); } else { pw.write(indent() + "<vely>0</vely>\n"); } if (detail.getVelocityZ() != null) { pw.write(indent() + "<velz>" + detail.getVelocityZ() + "</velz>\n"); } else { pw.write(indent() + "<velz>0</velz>\n"); } indentLevel--; pw.write(indent() + "</pointDetailVelocity>\n"); } if ((detail.getAccelerationX() != null) || (detail.getAccelerationY() != null) || (detail.getAccelerationZ() != null)) { pw.write(indent() + "<pointDetailAcceleration xsi:type=\"LocalCartesianAcceleration\">\n"); indentLevel++; if (detail.getAccelerationX() != null) { pw.write(indent() + "<accx>" + detail.getAccelerationX() + "</accx>\n"); } else { pw.write(indent() + "<accx>0</accx>\n"); } if (detail.getAccelerationY() != null) { pw.write(indent() + "<accy>" + detail.getAccelerationY() + "</accy>\n"); } else { pw.write(indent() + "<accy>0</accy>\n"); } if (detail.getAccelerationZ() != null) { pw.write(indent() + "<accz>" + detail.getAccelerationZ() + "</accz>\n"); } else { pw.write(indent() + "<accz>0</accz>\n"); } indentLevel--; pw.write(indent() + "</pointDetailAcceleration>\n"); } pw.write(indent() + "<pointDetailCovarianceMatrix xsi:type=\"CovarianceMatrixPositionVelocity\">"); Encode(detail.getCovarianceMatrix()); pw.write(indent() + "</pointDetailCovarianceMatrix>\n"); indentLevel--; } private void Encode( final CovarianceMatrix cov ) { indentLevel++; pw.write(indent() + "<covPosxPosx>" + cov.getCovPosXPosX() + "</covPosxPosx>\n"); pw.write(indent() + "<covPosyPosy>" + cov.getCovPosYPosY() + "</covPosyPosy>\n"); if (cov.getCovPosZPosZ() != null) { pw.write(indent() + "<covPoszPosz>" + cov.getCovPosZPosZ() + "</covPoszPosz>\n"); } if (cov.getCovPosXPosY() != null) { pw.write(indent() + "<covPosxPosy>" + cov.getCovPosXPosY() + "</covPosxPosy>\n"); } if (cov.getCovPosXPosZ() != null) { pw.write(indent() + "<covPosxPosz>" + cov.getCovPosXPosZ() + "</covPosxPosz>\n"); } if (cov.getCovPosYPosZ() != null) { pw.write(indent() + "<covPosyPosz>" + cov.getCovPosYPosZ() + "</covPosyPosz>\n"); } // these are also optional if (cov.getCovVelXVelX() != null) { pw.write(indent() + "<covVelxVelx>" + cov.getCovVelXVelX() + "</covVelxVelx>\n"); } if (cov.getCovVelYVelY() != null) { pw.write(indent() + "<covVelyVely>" + cov.getCovVelYVelY() + "</covVelyVely>\n"); } // if (cov.getCovVelZVelZ() != null) { pw.write(indent() + "<covVelzVelz>" + cov.getCovVelZVelZ() + "</covVelzVelz>\n"); } if (cov.getCovPosXVelX() != null) { pw.write(indent() + "<covPosxVelx>" + cov.getCovPosXVelX() + "</covPosxVelx>\n"); } if (cov.getCovPosXVelY() != null) { pw.write(indent() + "<covPosxVely>" + cov.getCovPosXVelY() + "</covPosxVely>\n"); } if (cov.getCovPosXVelZ() != null) { pw.write(indent() + "<covPosxVelz>" + cov.getCovPosXVelZ() + "</covPosxVelz>\n"); } if (cov.getCovPosYVelX() != null) { pw.write(indent() + "<covPosyVelx>" + cov.getCovPosYVelX() + "</covPosyVelx>\n"); } if (cov.getCovPosYVelY() != null) { pw.write(indent() + "<covPosyVely>" + cov.getCovPosYVelY() + "</covPosyVely>\n"); } if (cov.getCovPosYVelZ() != null) { pw.write(indent() + "<covPosyVelz>" + cov.getCovPosYVelZ() + "</covPosyVelz>\n"); } if (cov.getCovPosZVelX() != null) { pw.write(indent() + "<covPoszVelx>" + cov.getCovPosZVelX() + "</covPoszVelx>\n"); } if (cov.getCovPosZVelY() != null) { pw.write(indent() + "<covPoszVely>" + cov.getCovPosZVelY() + "</covPoszVely>\n"); } if (cov.getCovPosZVelZ() != null) { pw.write(indent() + "<covPoszVelz>" + cov.getCovPosZVelZ() + "</covPoszVelz>\n"); } if (cov.getCovVelXVelY() != null) { pw.write(indent() + "<covVelxVely>" + cov.getCovVelXVelY() + "</covVelxVely>\n"); } if (cov.getCovVelXVelZ() != null) { pw.write(indent() + "<covVelxVelz>" + cov.getCovVelXVelZ() + "</covVelxVelz>\n"); } if (cov.getCovVelYVelZ() != null) { pw.write(indent() + "<covVelyVelz>" + cov.getCovVelYVelZ() + "</covVelyVelz>\n"); } indentLevel--; } }