001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.text.translate; 018 019import java.io.IOException; 020import java.io.Writer; 021 022/** 023 * Translates codepoints to their XML numeric entity escaped value. 024 * 025 * @since 1.0 026 */ 027public class NumericEntityEscaper extends CodePointTranslator { 028 029 /** int value representing the lowest codepoint boundary. */ 030 private final int below; 031 /** int value representing the highest codepoint boundary. */ 032 private final int above; 033 /** whether to escape between the boundaries or outside them. */ 034 private final boolean between; 035 036 /** 037 * <p>Constructs a <code>NumericEntityEscaper</code> for the specified range. This is 038 * the underlying method for the other constructors/builders. The <code>below</code> 039 * and <code>above</code> boundaries are inclusive when <code>between</code> is 040 * <code>true</code> and exclusive when it is <code>false</code>. </p> 041 * 042 * @param below int value representing the lowest codepoint boundary 043 * @param above int value representing the highest codepoint boundary 044 * @param between whether to escape between the boundaries or outside them 045 */ 046 private NumericEntityEscaper(final int below, final int above, final boolean between) { 047 this.below = below; 048 this.above = above; 049 this.between = between; 050 } 051 052 /** 053 * <p>Constructs a <code>NumericEntityEscaper</code> for all characters. </p> 054 */ 055 public NumericEntityEscaper() { 056 this(0, Integer.MAX_VALUE, true); 057 } 058 059 /** 060 * <p>Constructs a <code>NumericEntityEscaper</code> below the specified value (exclusive). </p> 061 * 062 * @param codepoint below which to escape 063 * @return the newly created {@code NumericEntityEscaper} instance 064 */ 065 public static NumericEntityEscaper below(final int codepoint) { 066 return outsideOf(codepoint, Integer.MAX_VALUE); 067 } 068 069 /** 070 * <p>Constructs a <code>NumericEntityEscaper</code> above the specified value (exclusive). </p> 071 * 072 * @param codepoint above which to escape 073 * @return the newly created {@code NumericEntityEscaper} instance 074 */ 075 public static NumericEntityEscaper above(final int codepoint) { 076 return outsideOf(0, codepoint); 077 } 078 079 /** 080 * <p>Constructs a <code>NumericEntityEscaper</code> between the specified values (inclusive). </p> 081 * 082 * @param codepointLow above which to escape 083 * @param codepointHigh below which to escape 084 * @return the newly created {@code NumericEntityEscaper} instance 085 */ 086 public static NumericEntityEscaper between(final int codepointLow, final int codepointHigh) { 087 return new NumericEntityEscaper(codepointLow, codepointHigh, true); 088 } 089 090 /** 091 * <p>Constructs a <code>NumericEntityEscaper</code> outside of the specified values (exclusive). </p> 092 * 093 * @param codepointLow below which to escape 094 * @param codepointHigh above which to escape 095 * @return the newly created {@code NumericEntityEscaper} instance 096 */ 097 public static NumericEntityEscaper outsideOf(final int codepointLow, final int codepointHigh) { 098 return new NumericEntityEscaper(codepointLow, codepointHigh, false); 099 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override 105 public boolean translate(final int codepoint, final Writer out) throws IOException { 106 if (between) { 107 if (codepoint < below || codepoint > above) { 108 return false; 109 } 110 } else { 111 if (codepoint >= below && codepoint <= above) { 112 return false; 113 } 114 } 115 116 out.write("&#"); 117 out.write(Integer.toString(codepoint, 10)); 118 out.write(';'); 119 return true; 120 } 121}