import { AbstractMessageParser } from './abstract-message-parser' ; import { ParsedMessage } from './parsed-message' ; import { DOMUtilities } from './dom-utilities' ; import { ParsedMessagePartStartTag } from './parsed-message-part-start-tag' ; import { ParsedMessagePartEndTag } from './parsed-message-part-end-tag' ; import { ParsedMessagePartPlaceholder } from './parsed-message-part-placeholder' ; import { TagMapping } from './tag-mapping' ; import { ParsedMessagePartEmptyTag } from './parsed-message-part-empty-tag' ; import { ParsedMessagePartICUMessageRef } from './parsed-message-part-icu-message-ref' ; import { ParsedMessagePart , ParsedMessagePartType } from './parsed-message-part' ; import { ParsedMessagePartText } from './parsed-message-part-text' ; /**
 * Created by roobm on 10.05.2017.
 * A message parser for XMB
 */ export class XmbMessageParser extends AbstractMessageParser { param elementNode param message return protected processStartElement ( elementNode , message ) { const tagName = elementNode . tagName ; if ( tagName === 'ph' ) { const name = elementNode . getAttribute ( 'name' ) ; if ( ! name ) { return true ; } if ( name . startsWith ( 'INTERPOLATION' ) ) { const index = this . parsePlaceholderIndexFromName ( name ) ; message . addPlaceholder ( index , null ) ; return false ; } else if ( name . startsWith ( 'START_' ) ) { const tag = this . parseTagnameFromPhElement ( elementNode ) ; const idcounter = this . parseIdCountFromName ( name ) ; if ( tag ) { message . addStartTag ( tag , idcounter ) ; } return false ; } else if ( name . startsWith ( 'CLOSE_' ) ) { const tag = this . parseTagnameFromPhElement ( elementNode ) ; if ( tag ) { message . addEndTag ( tag ) ; } return false ; } else if ( new TagMapping ( ) . isEmptyTagPlaceholderName ( name ) ) { const emptyTagName = new TagMapping ( ) . getTagnameFromEmptyTagPlaceholderName ( name ) ; const idcounter = this . parseIdCountFromName ( name ) ; message . addEmptyTag ( emptyTagName , idcounter ) ; return false ; } else if ( name . startsWith ( 'ICU' ) ) { const index = this . parseICUMessageIndexFromName ( name ) ; message . addICUMessageRef ( index , null ) ; return false ; } } else if ( tagName === 'source' ) { return false ; } return true ; } param node return protected getICUMessageText ( node ) { const children = node . childNodes ; if ( children . length === 0 ) { return null ; } let firstChild = null ; let i ; for ( i = 0 ; i < children . length ; i ++ ) { const child = children . item ( i ) ; if ( child . nodeType !== child . ELEMENT_NODE || ( < Element > child ) . tagName !== 'source' ) { firstChild = child ; break ; } } if ( firstChild && firstChild . nodeType === firstChild . TEXT_NODE ) { if ( this . isICUMessageStart ( firstChild . textContent ) ) { const messageText = DOMUtilities . getXMLContent ( < Element > node ) ; if ( i > 0 ) { const reSource = new RegExp ( '<source[^>]*>.*</source>' , 'g' ) ; return messageText . replace ( reSource , '' ) ; } else { return messageText ; } } else { return null ; } } else { return null ; } } param elementNode param message protected processEndElement ( elementNode , message ) { } param name return private parsePlaceholderIndexFromName ( name ) { let indexString = '' ; if ( name === 'INTERPOLATION' ) { indexString = '0' ; } else { indexString = name . substring ( 'INTERPOLATION_' . length ) ; } return Number . parseInt ( indexString , 10 ) ; } param name return private parseICUMessageIndexFromName ( name ) { let indexString = '' ; if ( name === 'ICU' ) { indexString = '0' ; } else { indexString = name . substring ( 'ICU_' . length ) ; } return Number . parseInt ( indexString , 10 ) ; } param phElement private parseTagnameFromPhElement ( phElement ) { const exElement = DOMUtilities . getFirstElementByTagName ( phElement , 'ex' ) ; if ( exElement ) { const value = DOMUtilities . getPCDATA ( exElement ) ; if ( ! value || ! value . startsWith ( '<' ) || ! value . endsWith ( '>' ) ) { return null ; } if ( value . charAt ( 1 ) === '/' ) { return value . substring ( 2 , value . length - 1 ) ; } else { return value . substring ( 1 , value . length - 1 ) ; } } else { return null ; } } protected addXmlRepresentationToRoot ( message , rootElem ) { message . parts ( ) . forEach ( ( part ) => { const child = this . createXmlRepresentationOfPart ( part , rootElem ) ; if ( child ) { rootElem . appendChild ( child ) ; } } ) ; } protected createXmlRepresentationOfPart ( part , rootElem ) { switch ( part . type ) { case ParsedMessagePartType . TEXT : return this . createXmlRepresentationOfTextPart ( < ParsedMessagePartText > part , rootElem ) ; case ParsedMessagePartType . START_TAG : return this . createXmlRepresentationOfStartTagPart ( ( < ParsedMessagePartStartTag > part ) , rootElem ) ; case ParsedMessagePartType . END_TAG : return this . createXmlRepresentationOfEndTagPart ( ( < ParsedMessagePartEndTag > part ) , rootElem ) ; case ParsedMessagePartType . EMPTY_TAG : return this . createXmlRepresentationOfEmptyTagPart ( ( < ParsedMessagePartEmptyTag > part ) , rootElem ) ; case ParsedMessagePartType . PLACEHOLDER : return this . createXmlRepresentationOfPlaceholderPart ( ( < ParsedMessagePartPlaceholder > part ) , rootElem ) ; case ParsedMessagePartType . ICU_MESSAGE_REF : return this . createXmlRepresentationOfICUMessageRefPart ( ( < ParsedMessagePartICUMessageRef > part ) , rootElem ) ; } } param part param rootElem protected createXmlRepresentationOfStartTagPart ( part , rootElem ) { const phElem = rootElem . ownerDocument . createElement ( 'ph' ) ; const tagMapping = new TagMapping ( ) ; const nameAttrib = tagMapping . getStartTagPlaceholderName ( part . tagName ( ) , part . idCounter ( ) ) ; phElem . setAttribute ( 'name' , nameAttrib ) ; const exElem = rootElem . ownerDocument . createElement ( 'ex' ) ; exElem . appendChild ( rootElem . ownerDocument . createTextNode ( '<' + part . tagName ( ) + '>' ) ) ; phElem . appendChild ( exElem ) ; return phElem ; } param part param rootElem protected createXmlRepresentationOfEndTagPart ( part , rootElem ) { const phElem = rootElem . ownerDocument . createElement ( 'ph' ) ; const tagMapping = new TagMapping ( ) ; const nameAttrib = tagMapping . getCloseTagPlaceholderName ( part . tagName ( ) ) ; phElem . setAttribute ( 'name' , nameAttrib ) ; const exElem = rootElem . ownerDocument . createElement ( 'ex' ) ; exElem . appendChild ( rootElem . ownerDocument . createTextNode ( '</' + part . tagName ( ) + '>' ) ) ; phElem . appendChild ( exElem ) ; return phElem ; } param part param rootElem protected createXmlRepresentationOfEmptyTagPart ( part , rootElem ) { const phElem = rootElem . ownerDocument . createElement ( 'ph' ) ; const tagMapping = new TagMapping ( ) ; const nameAttrib = tagMapping . getEmptyTagPlaceholderName ( part . tagName ( ) , part . idCounter ( ) ) ; phElem . setAttribute ( 'name' , nameAttrib ) ; const exElem = rootElem . ownerDocument . createElement ( 'ex' ) ; exElem . appendChild ( rootElem . ownerDocument . createTextNode ( '<' + part . tagName ( ) + '>' ) ) ; phElem . appendChild ( exElem ) ; return phElem ; } param part param rootElem protected createXmlRepresentationOfPlaceholderPart ( part , rootElem ) { const phElem = rootElem . ownerDocument . createElement ( 'ph' ) ; let nameAttrib = 'INTERPOLATION' ; if ( part . index ( ) > 0 ) { nameAttrib = 'INTERPOLATION_' + part . index ( ) . toString ( 10 ) ; } phElem . setAttribute ( 'name' , nameAttrib ) ; const exElem = rootElem . ownerDocument . createElement ( 'ex' ) ; exElem . appendChild ( rootElem . ownerDocument . createTextNode ( nameAttrib ) ) ; phElem . appendChild ( exElem ) ; return phElem ; } param part param rootElem protected createXmlRepresentationOfICUMessageRefPart ( part , rootElem ) { const phElem = rootElem . ownerDocument . createElement ( 'ph' ) ; let nameAttrib = 'ICU' ; if ( part . index ( ) > 0 ) { nameAttrib = 'ICU_' + part . index ( ) . toString ( 10 ) ; } phElem . setAttribute ( 'name' , nameAttrib ) ; const exElem = rootElem . ownerDocument . createElement ( 'ex' ) ; exElem . appendChild ( rootElem . ownerDocument . createTextNode ( nameAttrib ) ) ; phElem . appendChild ( exElem ) ; return phElem ; } }