/*
 * 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.
 */

/* $Id: Marker.java 1805173 2017-08-16 10:50:04Z ssteiner $ */

package org.apache.fop.fo.flow;

import java.util.Map;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;

import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOTreeBuilderContext;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.PropertyListMaker;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.PropertyCache;

Class modelling the marker fo:markerobject.
/** * Class modelling the <a href="http://www.w3.org/TR/xsl/#fo_marker">marker</a> * <code>fo:marker</code>object. */
public class Marker extends FObjMixed { // The value of properties relevant for fo:marker. private String markerClassName; // End of property values private PropertyListMaker savePropertyListMaker; private Map descendantPropertyLists = new java.util.HashMap();
Create a marker fo.
Params:
/** * Create a marker fo. * * @param parent the parent {@link FONode} */
public Marker(FONode parent) { super(parent); }
{@inheritDoc}
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException { if (findAncestor(FO_FLOW) < 0) { invalidChildError(locator, getParent().getName(), FO_URI, getLocalName(), "rule.markerDescendantOfFlow"); } markerClassName = pList.get(PR_MARKER_CLASS_NAME).getString(); if (markerClassName == null || markerClassName.equals("")) { missingPropertyError("marker-class-name"); } }
Retrieve the property list of the given FONode descendant
Params:
  • foNode – the FONode whose property list is requested
Returns:the MarkerPropertyList for the given node
/** * Retrieve the property list of the given {@link FONode} * descendant * * @param foNode the {@link FONode} whose property list is requested * @return the {@link MarkerPropertyList} for the given node */
protected MarkerPropertyList getPropertyListFor(FONode foNode) { return (MarkerPropertyList) descendantPropertyLists.get(foNode); }
{@inheritDoc}
/** {@inheritDoc} */
public void startOfNode() { FOTreeBuilderContext builderContext = getBuilderContext(); // Push a new property list maker which will make MarkerPropertyLists. savePropertyListMaker = builderContext.getPropertyListMaker(); builderContext.setPropertyListMaker(new PropertyListMaker() { public PropertyList make(FObj fobj, PropertyList parentPropertyList) { PropertyList pList = new MarkerPropertyList(fobj, parentPropertyList); descendantPropertyLists.put(fobj, pList); return pList; } }); }
{@inheritDoc}
/** {@inheritDoc} */
public void endOfNode() throws FOPException { super.endOfNode(); // Pop the MarkerPropertyList maker. getBuilderContext().setPropertyListMaker(savePropertyListMaker); savePropertyListMaker = null; }
{@inheritDoc}
XSL Content Model: (#PCDATA|%inline;|%block;)*
Additionally: "An fo:marker may contain any formatting objects that are permitted as a replacement of any fo:retrieve-marker that retrieves the fo:marker's children." TODO implement "additional" constraint, possibly within fo:retrieve-marker
/** * {@inheritDoc} * <br>XSL Content Model: (#PCDATA|%inline;|%block;)* * <br><i>Additionally: "An fo:marker may contain any formatting objects that * are permitted as a replacement of any fo:retrieve-marker that retrieves * the fo:marker's children."</i> * TODO implement "additional" constraint, possibly within fo:retrieve-marker */
protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { if (!isBlockOrInlineItem(nsURI, localName)) { invalidChildError(loc, nsURI, localName); } } }
{@inheritDoc}
/** {@inheritDoc} */
protected boolean inMarker() { return true; }
Returns:the "marker-class-name" property
/** @return the "marker-class-name" property */
public String getMarkerClassName() { return markerClassName; }
{@inheritDoc}
/** {@inheritDoc} */
public String getLocalName() { return "marker"; }
{@inheritDoc}
Returns:Constants.FO_MARKER
/** * {@inheritDoc} * @return {@link org.apache.fop.fo.Constants#FO_MARKER} */
public int getNameId() { return FO_MARKER; }
{@inheritDoc}
/** {@inheritDoc} */
public String toString() { StringBuffer sb = new StringBuffer(super.toString()); sb.append(" {").append(getMarkerClassName()).append("}"); return sb.toString(); }
An implementation of PropertyList which only stores the explicitly specified properties/attributes as bundles of name-value-namespace strings
/** * An implementation of {@link PropertyList} which only stores the explicitly * specified properties/attributes as bundles of name-value-namespace * strings */
protected class MarkerPropertyList extends PropertyList implements Attributes {
the array of attributes
/** the array of attributes **/
private MarkerAttribute[] attribs;
Overriding default constructor
Params:
  • fobj – the FObj to attach
  • parentPropertyList – ignored
/** * Overriding default constructor * * @param fobj the {@link FObj} to attach * @param parentPropertyList ignored */
public MarkerPropertyList(FObj fobj, PropertyList parentPropertyList) { /* ignore parentPropertyList * won't be used because the attributes will be stored * without resolving */ super(fobj, null); }
Override that doesn't convert the attributes to Property instances, but simply stores the attributes for later processing. {@inheritDoc}
/** * Override that doesn't convert the attributes to {@link Property} * instances, but simply stores the attributes for later processing. * * {@inheritDoc} */
public void addAttributesToList(Attributes attributes) throws ValidationException { this.attribs = new MarkerAttribute[attributes.getLength()]; String name; String value; String namespace; String qname; for (int i = attributes.getLength(); --i >= 0;) { namespace = attributes.getURI(i); qname = attributes.getQName(i); name = attributes.getLocalName(i); value = attributes.getValue(i); this.attribs[i] = MarkerAttribute.getInstance(namespace, qname, name, value); } }
Null implementation; not used by this type of PropertyList.
Params:
  • propId – the propert id
  • value – the property value
/** * Null implementation; not used by this type of {@link PropertyList}. * @param propId the propert id * @param value the property value */
public void putExplicit(int propId, Property value) { //nop }
Null implementation; not used by this type of PropertyList.
Params:
  • propId – the propert id
Returns:the property id
/** * Null implementation; not used by this type of {@link PropertyList}. * @param propId the propert id * @return the property id */
public Property getExplicit(int propId) { return null; }
{@inheritDoc}
/** {@inheritDoc} */
public int getLength() { if (attribs == null) { return 0; } else { return attribs.length; } }
{@inheritDoc}
/** {@inheritDoc} */
public String getURI(int index) { if (attribs != null && index < attribs.length && index >= 0 && attribs[index] != null) { return attribs[index].namespace; } else { return null; } }
{@inheritDoc}
/** {@inheritDoc} */
public String getLocalName(int index) { if (attribs != null && index < attribs.length && index >= 0 && attribs[index] != null) { return attribs[index].name; } else { return null; } }
{@inheritDoc}
/** {@inheritDoc} */
public String getQName(int index) { if (attribs != null && index < attribs.length && index >= 0 && attribs[index] != null) { return attribs[index].qname; } else { return null; } }
Default implementation; not used.
Params:
  • index – a type index
Returns:type string
/** * Default implementation; not used. * @param index a type index * @return type string */
public String getType(int index) { return "CDATA"; }
{@inheritDoc}
/** {@inheritDoc} */
public String getValue(int index) { if (attribs != null && index < attribs.length && index >= 0 && attribs[index] != null) { return attribs[index].value; } else { return null; } }
{@inheritDoc}
/** {@inheritDoc} */
public int getIndex(String name, String namespace) { int index = -1; if (attribs != null && name != null && namespace != null) { for (int i = attribs.length; --i >= 0;) { if (attribs[i] != null && namespace.equals(attribs[i].namespace) && name.equals(attribs[i].name)) { break; } } } return index; }
{@inheritDoc}
/** {@inheritDoc} */
public int getIndex(String qname) { int index = -1; if (attribs != null && qname != null) { for (int i = attribs.length; --i >= 0;) { if (attribs[i] != null && qname.equals(attribs[i].qname)) { break; } } } return index; }
Default implementation; not used
Params:
  • name – a type name
  • namespace – a type namespace
Returns:type string
/** * Default implementation; not used * @param name a type name * @param namespace a type namespace * @return type string */
public String getType(String name, String namespace) { return "CDATA"; }
Default implementation; not used
Params:
  • qname – a type name
Returns:type string
/** * Default implementation; not used * @param qname a type name * @return type string */
public String getType(String qname) { return "CDATA"; }
{@inheritDoc}
/** {@inheritDoc} */
public String getValue(String name, String namespace) { int index = getIndex(name, namespace); if (index > 0) { return getValue(index); } return null; }
{@inheritDoc}
/** {@inheritDoc} */
public String getValue(String qname) { int index = getIndex(qname); if (index > 0) { return getValue(index); } return null; } }
Convenience inner class
/** Convenience inner class */
public static final class MarkerAttribute { private static final PropertyCache<MarkerAttribute> CACHE = new PropertyCache<MarkerAttribute>();
namespace
/** namespace */
private String namespace;
qualfied name
/** qualfied name */
private String qname;
local name
/** local name */
private String name;
value
/** value */
private String value;
Main constructor
Params:
  • namespace – the namespace URI
  • qname – the qualified name
  • name – the name
  • value – the value
/** * Main constructor * @param namespace the namespace URI * @param qname the qualified name * @param name the name * @param value the value */
private MarkerAttribute(String namespace, String qname, String name, String value) { this.namespace = namespace; this.qname = qname; this.name = (name == null ? qname : name); this.value = value; }
Convenience method, reduces the number of distinct MarkerAttribute instances
Params:
  • namespace – the attribute namespace
  • qname – the fully qualified name of the attribute
  • name – the attribute name
  • value – the attribute value
Returns:the single MarkerAttribute instance corresponding to the name/value-pair
/** * Convenience method, reduces the number * of distinct MarkerAttribute instances * * @param namespace the attribute namespace * @param qname the fully qualified name of the attribute * @param name the attribute name * @param value the attribute value * @return the single MarkerAttribute instance corresponding to * the name/value-pair */
private static MarkerAttribute getInstance( String namespace, String qname, String name, String value) { return CACHE.fetch( new MarkerAttribute(namespace, qname, name, value)); }
{@inheritDoc}
/** {@inheritDoc} */
public int hashCode() { int hash = 17; hash = (37 * hash) + (this.namespace == null ? 0 : this.namespace.hashCode()); hash = (37 * hash) + (this.qname == null ? 0 : this.qname.hashCode()); hash = (37 * hash) + (this.name == null ? 0 : this.name.hashCode()); hash = (37 * hash) + (this.value == null ? 0 : this.value.hashCode()); return hash; }
{@inheritDoc}
/** {@inheritDoc} */
public boolean equals(Object o) { if (this == o) { return true; } if (o instanceof MarkerAttribute) { MarkerAttribute attr = (MarkerAttribute) o; return (attr.namespace != null && attr.namespace.equals(this.namespace)) && (attr.qname != null && attr.qname.equals(this.qname)) && (attr.name != null && attr.name.equals(this.name)) && (attr.value != null && attr.value.equals(this.value)); } else { return false; } } } }