/** Ċ Ġ* ĠParser Ġfor Ġversion Ġ 1 ĠSm il Ġfiles . Ċ Ġ* Ċ Ġ* ĠExtract s Ġthe Ġcontents Ġof Ġthe Ġfiles , Ġincluding Ġthe Ġsequence Ġof ĠSEQ Ċ Ġ* Ġ( sequential ) Ġand ĠPAR Ġ( parallel ) Ġelements . ĠThese Ġoften Ġcontain Ġadditional Ċ Ġ* Ġelements Ġe . g . Ġtext Ġand Ġaudio Ġcontents . Ċ Ġ* Ċ Ġ* ĠTODO ( jh art y ): Ċ Ġ* ĠWe Ġneed Ġto Ġdetermine : Ċ Ġ* Ġ 1 . ĠCan ĠPAR Ġelements Ġbe Ġnested Ċ Ġ* Ġ 2 . ĠCan ĠSEQ Ġelements Ġbe Ġnested Ċ Ġ* Ċ Ġ* ĠI Ġalso Ġneed Ġto Ġdetermine Ġwhether Ġthe Ġcurrent Ġstate Ġmachine Ġis Ġthe Ċ Ġ* Ġappropriate Ġmodel Ġto Ġrepresent Ġthe Ġcontents Ġof ĠSM IL Ġfiles . ĠIt 's Ġcertainly Ċ Ġ* Ġbroken Ġcurrently . Ċ Ġ*/ Ċ package Ġcom . example . ader . sm il Ċ Ċ import Ġjava . io . ByteArray InputStream Ċ import Ġjava . io . IOException Ċ import Ġjava . io . InputStream Ċ import Ġjava . util . logging . Logger Ċ Ċ import Ġjavax . xml . parsers . Parser ConfigurationException Ċ import Ġjavax . xml . parsers . SAX Parser Factory Ċ Ċ import Ġorg . xml . sax . Attributes Ċ import Ġorg . xml . sax . Input Source Ċ import Ġorg . xml . sax . SAX Exception Ċ import Ġorg . xml . sax . XML Reader Ċ import Ġorg . xml . sax . helpers . Default Handler Ċ Ċ import Ġcom . example . ader . Dummy D td Resolver Ċ import Ġjava . lang . Double . parseDouble Ċ import Ġcom . example . ader . sm il . Sequence Element Builder Ċ Ċ /** Ċ Ġ* ĠParser Ġfor ĠSM IL Ġfiles . Ċ Ġ* Ċ Ġ* ĠTODO ( jh art y ): ĠThink Ġcarefully Ġhow Ġto Ġtest Ġthe Ġparsing Ġfor Ġmore Ġcomplex Ċ Ġ* Ġcontents . ĠThe Ġstate Ġtransitions Ġmay Ġbe Ġerror - pr one Ġand Ġthe Ġcode Ġin Ċ Ġ* Ġstart Element Ġin Ġparticular Ġis Ġof Ġconcern . Ċ Ġ* Ċ Ġ* ĠNote : ĠMal formed Ġor Ġinvalid Ġcontent Ġof Ġa ĠSM IL Ġfile Ġstops Ġelements Ġfrom Ġbeing Ċ Ġ* Ġcreated . ĠAt Ġthe Ġmoment Ġno Ġerror Ġis Ġreported Ġin Ġsuch Ġcases . ĠThis Ġwas Ċ Ġ* Ġe vid enced Ġwhen ĠI Ġtested Ġwith Ġa Ġsimple Ġfile Ġcontaining Ġa Ġsingle Ġaudio Ċ Ġ* Ġelement , Ġwhen Ġno Ġelements Ġwere Ġgenerated Ġuntil ĠI Ġhad Ġadded Ġall Ġthe Ċ Ġ* Ġattributes Ġcorrectly . ĠWe Ġcould Ġadd Ġinformation al Ġmessages Ġto Ġthe Ġcreate Ċ Ġ* Ġmethods . Ċ Ġ* Ċ Ġ* Ġ@ author Ġj h art y Ċ Ġ*/ Ċ class ĠSm il Parser Ġ: ĠDefault Handler () Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlog Ġ= ĠLogger . getLogger ( Sm il Parser :: class . java . simple Name ) ĊĊĠĠĠ Ġprivate Ġvar Ġcurrent Container : ĠContainer Element ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġcurrent Element : ĠSm il Element ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġstate : ĠState ? Ġ= Ġnull ĊĊĠĠĠ Ġprivate Ġenum Ġclass ĠState Ġ{ ĊĠĠĠĠĠĠĠ ĠINIT , ĊĠĠĠĠĠĠĠ ĠSEQ , ĊĠĠĠĠĠĠĠ ĠPAR A ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠParse Ġcontents Ġthat Ġshould Ġcontain Ġthe ĠSm il ĠFile Ġstructure . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠUseful Ġfor Ġtesting Ġthe Ġparsing . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġcontent Ġthe Ġcontent Ġto Ġparse ĊĠĠĠĠ Ġ* Ġ@ return ĠSequence Ġof ĠElements . ĊĠĠĠĠ Ġ* Ġ@ throws ĠIOException ĊĠĠĠĠ Ġ* Ġ@ throws ĠSAX Exception ĊĠĠĠĠ Ġ* Ġ@ throws ĠParser ConfigurationException ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class , ĠSAX Exception :: class , ĠParser ConfigurationException :: class ) ĊĠĠĠ Ġfun Ġparse ( content : ĠString ): ĠSequence Element ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġthis . parse ( ByteArray InputStream ( content . toByteArray ())) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠMany Ġthanks Ġto Ġthe Ġfollowing Ġlink Ġwhich Ġprovided Ġthe Ġfinal Ġpiece Ġfor Ġme , ĊĠĠĠ Ġ// Ġhttp :// stackoverflow . com / questions / 2 9 3 7 2 8 / e - is - not - correct ly - parsed ĊĠĠĠ Ġ@ Throws ( IOException :: class , ĠSAX Exception :: class , ĠParser ConfigurationException :: class ) ĊĠĠĠ Ġ@ Jvm Over loads ĊĠĠĠ Ġfun Ġparse ( stream : ĠInputStream , Ġencoding : ĠString Ġ= Ġ" UTF - 8 "): ĠSequence Element ? Ġ{ ĊĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . INIT ĊĠĠĠĠĠĠĠ Ġval Ġfactory Ġ= ĠSAX Parser Factory . newInstance () ĊĠĠĠĠĠĠĠ Ġval Ġparser Ġ= Ġfactory . new SAX Parser (). xml Reader ĊĠĠĠĠĠĠĠ Ġparser . entity Resolver Ġ= ĠDummy D td Resolver () ĊĠĠĠĠĠĠĠ Ġparser . content Handler Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġval Ġinput Ġ= ĠInput Source ( stream ) ĊĠĠĠĠĠĠĠ Ġinput . encoding Ġ= Ġencoding ĊĊĠĠĠĠĠĠĠ Ġparser . parse ( input ) ĊĠĠĠĠĠĠĠ Ġthrow ĠException () ĊĠĠĠĠĠĠĠ Ġ// return Ġroot Sequence . Build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġby Ġthe ĠSAX ĠParser Ġfor Ġthe Ġstart Ġof Ġevery Ġelement Ġdiscovered . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠTODO ( jh art y ): ĠRew ork , Ġtest , Ġand Ġsimplify . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( SAX Exception :: class ) ĊĠĠĠ Ġoverride Ġfun Ġstart Element ( uri : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocal Name : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġq Name : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġattributes : ĠAttributes ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġsuper . start Element ( uri , Ġlocal Name , Ġq Name , Ġattributes ) ĊĊĠĠĠĠĠĠĠ Ġval Ġname Ġ= Ġif Ġ( local Name . length Ġ!= Ġ 0 ) Ġlocal Name ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġq Name ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( state ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSm il Parser . State . INIT Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" init Ġ" Ġ+ Ġname ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(" seq ". equals ( name , Ġignore Case Ġ= Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . SEQ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġcreate Sequence Element ( attributes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSm il Parser . State . SEQ Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" seq Ġ" Ġ+ Ġname ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġseq Ġ= Ġcurrent Element Ġas ĠSequence Element ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" par ". equals ( name , Ġignore Case Ġ= Ġtrue ) Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . PARA ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpar Ġ= ĠParallel Element ( seq ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseq . elements . add ( par ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġpar ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" text ". equals ( name , Ġignore Case Ġ= Ġtrue ) Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtext Element Ġ= Ġcreate Text Element ( attributes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseq . elements . add ( createText Element ( attributes )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġtext Element ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" audio ". equals ( name , Ġignore Case Ġ= Ġtrue ) Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġaudio Element Ġ= Ġcreate Audio Element ( attributes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseq . elements . add ( audio Element ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġaudio Element ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠSm il Parser . State . PARA Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" para Ġ" Ġ+ Ġname ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpar Ġ= Ġcurrent Element Ġas ĠParallel Element ? ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(" text ". equals ( name , Ġignore Case Ġ= Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpar !!. text Element Ġ= Ġcreate Text Element ( attributes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ(" audio ". equals ( name , Ġignore Case Ġ= Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġseq Ġ= ĠSequence Element ( current Element !! Ġas ĠContainer Element , Ġ. 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpar !!. audio Sequence Ġ= Ġseq ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġseq . elements . add ( create Audio Element ( attributes )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ(" seq ". equals ( name , Ġignore Case Ġ= Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġseq Ġ= Ġcreate Sequence Element ( attributes ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpar !!. audio Sequence Ġ= Ġseq ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġseq ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . SEQ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCalled Ġby Ġthe ĠSAX ĠParser Ġfor Ġthe Ġend Ġof Ġevery Ġelement . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( SAX Exception :: class ) ĊĠĠĠ Ġoverride Ġfun Ġend Element ( uri : ĠString , Ġlocal Name : ĠString ?, Ġq Name : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠTODO ( jh art y ): Ġdetermine Ġwhen Ġto Ġrestore Ġthe Ġstate Ġto Ġthe Ġprevious ĊĠĠĠĠĠĠĠ Ġ// Ġvalue . ĠCurrently Ġwe Ġoverwrite Ġthe Ġcontents Ġof Ġa Ġnested Ġparallel ĊĠĠĠĠĠĠĠ Ġ// Ġelement Ġbecause Ġthe Ġcurrent Ġimplementation Ġis Ġfl aw ed . ĊĊĠĠĠĠĠĠĠ Ġval Ġelement Name Ġ= Ġlocal Name Ġ?: Ġq Name ĊĊĠĠĠĠĠĠĠ Ġ// ĠOK , Ġlet 's Ġsee Ġif Ġwe Ġcan Ġdetermine Ġthe Ġparent 's Ġtype Ġ( SEQ / PAR ) ĊĠĠĠĠĠĠĠ Ġif Ġ( element Name . equals (" seq ", Ġignore Case Ġ= Ġtrue ) Ġ|| Ġelement Name . equals (" par ", Ġignore Case Ġ= Ġtrue )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparent Ġ= Ġ( current Element !! Ġas ĠContainer Element ). parent ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( parent Ġis ĠParallel Element ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" End : Ġ$ element Name , Ġparent Ġelement Ġtype : ĠPAR ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġparent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . PARA ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( parent Ġis ĠSequence Element ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" End : Ġ$ element Name , Ġparent Ġelement Ġtype : ĠSEQ ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcurrent Element Ġ= Ġparent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . SEQ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info (" End : Ġ" Ġ+ Ġelement Name ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġsuper . end Element ( uri , Ġlocal Name , Ġq Name ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Sequence Element ( attributes : ĠAttributes ): ĠSequence Element Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġduration Ġ= Ġ 0 . 0 ĊĠĠĠĠĠĠĠ Ġif Ġ( attributes . getValue (" dur ") Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġduration Ġ= Ġparse Double ( attributes ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. getValue (" dur "). replace (" s ", Ġ"")) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĠSequence Element ( current Element Ġas ĠContainer Element , Ġduration ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Audio Element ( attributes : ĠAttributes ): ĠAudio Element Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠAudio Element ( current Element !! , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġattributes . getValue (" src "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO : Ġsupport Ġmore Ġtime Ġformats ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparse Double ( attributes . getValue (" clip - begin "). replace (" n pt =", Ġ""). replace (" s ", Ġ"") ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparse Double ( attributes . getValue (" clip - end "). replace (" n pt =", Ġ""). replace (" s ", Ġ"") ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġattributes . getValue (" id ")) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Text Element ( attributes : ĠAttributes ): ĠText Element Ġ{ ĊĠĠĠĠĠĠĠ Ġ// TODO : Ġhandle Ġinline Ġtext ĊĠĠĠĠĠĠĠ Ġreturn ĠText Element ( current Element !! , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġattributes . getValue (" src "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġattributes . getValue (" id ")) ĊĠĠĠ Ġ} Ċ } Ċ