blob: 7f351be71970687032470c1f99a97c811620b24e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.daffodil.processors.unparsers
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.processors.OutputNewLineEv
import org.apache.daffodil.processors.InfosetCachedEvaluatable
import org.apache.daffodil.processors.Evaluatable
import org.apache.daffodil.processors.ParseOrUnparseState
import org.apache.daffodil.util.Maybe
import org.apache.daffodil.cookers.EntityReplacer
import org.apache.daffodil.dsom.DPathCompileInfo
class NilStringLiteralForUnparserEv(
tci: DPathCompileInfo,
maybeOutputNewLineEv: Maybe[OutputNewLineEv],
stringLiteralRaw: String)
extends Evaluatable[String](tci)
with InfosetCachedEvaluatable[String] {
override lazy val runtimeDependencies = maybeOutputNewLineEv.toList
override protected def compute(state: ParseOrUnparseState): String = {
val endMarker = "__daffodil_stringLiteralForUnparser_endMarker__"
Assert.invariant(!stringLiteralRaw.endsWith(endMarker))
val rawWithEndMark = stringLiteralRaw + endMarker
EntityReplacer { er =>
val cookedWithEndMark = er.replaceForUnparse(rawWithEndMark)
val chunksSeparatedByNL = cookedWithEndMark.split(er.markerForNL).toSeq
val last = chunksSeparatedByNL.last
val butLast = chunksSeparatedByNL.take(chunksSeparatedByNL.length - 1)
val chunks =
if (last == endMarker) {
// this means the original string ended with a %NL;
// because the endMarker is all by itself.
butLast :+ "" // replace it by an empty string
} else {
// the original string did not end with a %NL;
// so that means whatever the last token is, it has our endMarker
// glued onto it, and we must remove that.
Assert.invariant(last.endsWith(endMarker))
butLast :+ last.replace(endMarker, "")
}
if (chunks.length == 1) {
// there are no NL entities. There is only a single chunk.
chunks.head
} else {
tci.schemaDefinitionUnless(
maybeOutputNewLineEv.isDefined,
"Property dfdl:outputNewLine is required, but it is not defined.")
val nl = maybeOutputNewLineEv.get.evaluate(state)
val sl = chunks.mkString(nl)
sl
}
}
}
}