All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cz.muni.fi.mir.mathmlcanonicalization.modules.MfencedReplacer Maven / Gradle / Ivy

Go to download

MathMLCanonicalizer is able to canonicalize MathML input. Modular architecture allows to set up canonicalization features according to users needs.

There is a newer version: 1.3.1
Show newest version
/**
 * Copyright 2013 MIR@MU Project
 *
 * Licensed 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 cz.muni.fi.mir.mathmlcanonicalization.modules;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.filter.ElementFilter;

/**
 * Replace mfenced elements in MathML for equivalent.
 *
 * 
Input
* Well-formed MathML, preserved non-default attributes in <mfenced> tags, * not processed by MrowMinimizer yet *
Output
* The original code containing no <mfenced> elements, originally fenced * formulae are enclosed in <mrow> tag, contain delimiters and separators * (from <mfenced> attributes) in <mo> elements, inner content is * placed into another <mrow> element. Module can be configured not to add * mrow outside and inside or your own fixed or default parentheses and * separators for fenced expressions can be specified. *
Example
*
 <mfenced open="[">
 *     <mi>x<mi>
 *     <mi>y<mi>
 * </mfenced>
is transformed to
 * <mrow>
 *     <mo>[</mo>
 *     <mrow>
 *         <mi>x<mi>
 *         <mo>,</mo>
 *         <mi>y<mi>
 *     </mrow>
 *     <mo>)</mo>
 * </mrow>
* * @author David Formanek */ public class MfencedReplacer extends AbstractModule implements DOMModule { /** * Path to the property file with module settings. */ private static final String PROPERTIES_FILENAME = "MfencedReplacer.properties"; private static final Logger LOGGER = Logger.getLogger(MfencedReplacer.class.getName()); // MathML attributes private static final String OPEN_FENCE = "open"; private static final String CLOSE_FENCE = "close"; private static final String SEPARATORS = "separators"; // properties key names private static final String DEFAULT_OPEN = "open"; private static final String DEFAULT_CLOSE = "close"; private static final String DEFAULT_SEPARATORS = "separators"; private static final String FORCE_DEFAULT_OPEN = "forceopen"; private static final String FORCE_DEFAULT_CLOSE = "forceclose"; private static final String FORCE_DEFAULT_SEPARATORS = "forceseparators"; private static final String ADD_OUTER_ROW = "outermrow"; private static final String ADD_INNER_ROW = "innermrow"; public MfencedReplacer() { loadProperties(PROPERTIES_FILENAME); } @Override public void execute(final Document doc) { if (doc == null) { throw new NullPointerException("doc"); } final List toReplace = new ArrayList(); for (Element mfenced : doc.getDescendants(new ElementFilter(FENCED))) { toReplace.add(mfenced); } if (toReplace.isEmpty()) { LOGGER.fine("No mfenced elements found"); return; } for (Element mfenced : toReplace) { replaceMfenced(mfenced); } } private void replaceMfenced(final Element mfencedElement) { assert mfencedElement != null; final char[] separators = getSeparators(mfencedElement); final Namespace ns = mfencedElement.getNamespace(); final List children = mfencedElement.getChildren(); final int nChildren = children.size(); final int last = Math.min(separators.length - 1, nChildren - 2); Element insideFence = null; if (nChildren == 1 && children.get(0).getName().equals(ROW)) { // we do not want to add another mrow insideFence = children.get(0).detach(); } else if (nChildren != 0) { insideFence = new Element(ROW, ns); for (int i = 0; i < nChildren; i++) { // add separator if (i > 0 && last >= 0) { // not before first or when blank separators char separatorChar = separators[(i - 1 > last) ? last : i - 1]; String separatorStr = Character.toString(separatorChar); insideFence.addContent(new Element(OPERATOR, ns).setText(separatorStr)); } // add original child insideFence.addContent(children.get(0).detach()); } } replaceMfenced(mfencedElement, insideFence); } private void replaceMfenced(final Element mfencedElement, final Element insideContent) { assert mfencedElement != null; // but insideContent can be null final Namespace ns = mfencedElement.getNamespace(); Element replacement = new Element(ROW, ns); String openStr = getProperty(DEFAULT_OPEN); String closeStr = getProperty(DEFAULT_CLOSE); if (openStr.isEmpty() || closeStr.isEmpty()) { LOGGER.warning("Default open or close fence not set"); } if (!isEnabled(FORCE_DEFAULT_OPEN)) { openStr = mfencedElement.getAttributeValue(OPEN_FENCE, openStr); } if (!isEnabled(FORCE_DEFAULT_CLOSE)) { closeStr = mfencedElement.getAttributeValue(CLOSE_FENCE, closeStr); } replacement.addContent(new Element(OPERATOR, ns).setText(openStr)); if (insideContent != null) { if (isEnabled(ADD_INNER_ROW)) { replacement.addContent(insideContent); } else { replacement.addContent(insideContent.removeContent()); } } replacement.addContent(new Element(OPERATOR, ns).setText(closeStr)); final Element parent = mfencedElement.getParentElement(); final int index = parent.indexOf(mfencedElement); parent.removeContent(index); if (isEnabled(ADD_OUTER_ROW)) { parent.addContent(index, replacement); } else { parent.addContent(index, replacement.removeContent()); } LOGGER.fine("Mfenced element converted"); } private char[] getSeparators(final Element element) { assert element != null; if (isEnabled(FORCE_DEFAULT_SEPARATORS)) { return getProperty(DEFAULT_SEPARATORS).toCharArray(); } return element.getAttributeValue(SEPARATORS, getProperty(DEFAULT_SEPARATORS)).trim().toCharArray(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy