/*
 * 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: LayoutContext.java 1610839 2014-07-15 20:25:58Z vhennebert $ */

package org.apache.fop.layoutmgr;

import java.util.Collections;
import java.util.List;

import org.apache.fop.fo.Constants;
import org.apache.fop.layoutmgr.inline.AlignmentContext;
import org.apache.fop.layoutmgr.inline.HyphContext;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.WritingMode;


This class is used to pass information to the getNextKnuthElements() method. It is set up by higher level LM and used by lower level LM.
/** * This class is used to pass information to the getNextKnuthElements() * method. It is set up by higher level LM and used by lower level LM. */
public final class LayoutContext {
Generated break possibility is first in a new area
/** Generated break possibility is first in a new area */
public static final int NEW_AREA = 0x01;
If this flag is set, it indicates that any break-before values other than "auto" should not cause a mandatory break as this break was already handled by a parent layout manager.
/** * If this flag is set, it indicates that any break-before values other than "auto" should * not cause a mandatory break as this break was already handled by a parent layout manager. */
public static final int SUPPRESS_BREAK_BEFORE = 0x02; public static final int FIRST_AREA = 0x04; public static final int LAST_AREA = 0x08; public static final int RESOLVE_LEADING_SPACE = 0x10; private static final int TREAT_AS_ARTIFACT = 0x20; private int flags; // Contains some set of flags defined above
Total available stacking dimension for a "galley-level" layout manager in block-progression-direction. It is passed by the parent LM. These LM may wish to pass this information down to lower level LM to allow them to optimize returned break possibilities.
/** * Total available stacking dimension for a "galley-level" layout * manager in block-progression-direction. It is passed by the * parent LM. * These LM <b>may</b> wish to pass this information down to lower * level LM to allow them to optimize returned break possibilities. */
private MinOptMax stackLimitBP;
to keep track of spanning in multi-column layout
/** to keep track of spanning in multi-column layout */
private int currentSpan = Constants.NOT_SET; private int nextSpan = Constants.NOT_SET;
inline-progression-dimension of nearest ancestor reference area
/** inline-progression-dimension of nearest ancestor reference area */
private int refIPD; //TODO After the split of stackLimit into stackLimitBP and stackLimitIP there's now some //overlap with refIPD. Need to investigate how best to refactor that.
the writing mode established by the nearest ancestor reference area
/** the writing mode established by the nearest ancestor reference area */
private WritingMode writingMode = WritingMode.LR_TB;
Current pending space-after or space-end from preceding area
/** Current pending space-after or space-end from preceding area */
private SpaceSpecifier trailingSpace;
Current pending space-before or space-start from ancestor areas
/** Current pending space-before or space-start from ancestor areas */
private SpaceSpecifier leadingSpace;
A list of pending marks (border and padding) on the after edge when a page break occurs. May be null.
/** * A list of pending marks (border and padding) on the after edge when a page break occurs. * May be null. */
private List pendingAfterMarks;
A list of pending marks (border and padding) on the before edge when a page break occurs. May be null.
/** * A list of pending marks (border and padding) on the before edge when a page break occurs. * May be null. */
private List pendingBeforeMarks;
Current hyphenation context. May be null.
/** Current hyphenation context. May be null. */
private HyphContext hyphContext;
Alignment in BP direction
/** Alignment in BP direction */
private int bpAlignment = Constants.EN_START;
Stretch or shrink value when making areas.
/** Stretch or shrink value when making areas. */
private double ipdAdjust;
Stretch or shrink value when adding spaces.
/** Stretch or shrink value when adding spaces. */
private double dSpaceAdjust; private AlignmentContext alignmentContext;
Amount of space before / start
/** Amount of space before / start */
private int spaceBefore;
Amount of space after / end
/** Amount of space after / end */
private int spaceAfter;
Amount of space to reserve at the beginning of each line
/** Amount of space to reserve at the beginning of each line */
private int lineStartBorderAndPaddingWidth;
Amount of space to reserve at the end of each line
/** Amount of space to reserve at the end of each line */
private int lineEndBorderAndPaddingWidth; private int breakBefore; private int breakAfter; private Keep pendingKeepWithNext = Keep.KEEP_AUTO; private Keep pendingKeepWithPrevious = Keep.KEEP_AUTO; private int disableColumnBalancing; public static LayoutContext newInstance() { return new LayoutContext(0); } public static LayoutContext copyOf(LayoutContext copy) { return new LayoutContext(copy); }
Returns a descendant of the given layout context. The new context is the same as what would have been created by newInstance(), except for inheritable properties that are passed on by the parent. At the moment, the only inheritable property is the value returned by treatAsArtifact().
/** * Returns a descendant of the given layout context. The new context is the same as * what would have been created by {@link #newInstance()}, except for inheritable * properties that are passed on by the parent. At the moment, the only inheritable * property is the value returned by {@link #treatAsArtifact()}. */
public static LayoutContext offspringOf(LayoutContext parent) { LayoutContext offspring = new LayoutContext(0); offspring.setTreatAsArtifact(parent.treatAsArtifact()); return offspring; } private LayoutContext(LayoutContext parentLC) { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; this.writingMode = parentLC.writingMode; setStackLimitBP(parentLC.getStackLimitBP()); this.leadingSpace = parentLC.leadingSpace; //??? this.trailingSpace = parentLC.trailingSpace; //??? this.hyphContext = parentLC.hyphContext; this.bpAlignment = parentLC.bpAlignment; this.dSpaceAdjust = parentLC.dSpaceAdjust; this.ipdAdjust = parentLC.ipdAdjust; this.alignmentContext = parentLC.alignmentContext; this.lineStartBorderAndPaddingWidth = parentLC.lineStartBorderAndPaddingWidth; this.lineEndBorderAndPaddingWidth = parentLC.lineEndBorderAndPaddingWidth; copyPendingMarksFrom(parentLC); this.pendingKeepWithNext = parentLC.pendingKeepWithNext; this.pendingKeepWithPrevious = parentLC.pendingKeepWithPrevious; // Copy other fields as necessary. this.disableColumnBalancing = parentLC.disableColumnBalancing; } private LayoutContext(int flags) { this.flags = flags; this.refIPD = 0; stackLimitBP = MinOptMax.ZERO; leadingSpace = null; trailingSpace = null; }
Params:
  • source – from which pending marks are copied
/** @param source from which pending marks are copied */
public void copyPendingMarksFrom(LayoutContext source) { if (source.pendingAfterMarks != null) { this.pendingAfterMarks = new java.util.ArrayList(source.pendingAfterMarks); } if (source.pendingBeforeMarks != null) { this.pendingBeforeMarks = new java.util.ArrayList(source.pendingBeforeMarks); } }
Params:
  • flags – to set
/** @param flags to set */
public void setFlags(int flags) { setFlags(flags, true); }
Params:
  • flags – to set or clear
  • bSet – true to set, false to clear
/** * @param flags to set or clear * @param bSet true to set, false to clear */
public void setFlags(int flags, boolean bSet) { if (bSet) { this.flags |= flags; } else { this.flags &= ~flags; } }
Params:
  • flags – to clear
/** @param flags to clear */
public void unsetFlags(int flags) { setFlags(flags, false); }
Returns:true if new area is set
/** @return true if new area is set */
public boolean isStart() { return ((this.flags & NEW_AREA) != 0); }
Returns:true if new area is set and leading space is non-null
/** @return true if new area is set and leading space is non-null */
public boolean startsNewArea() { return ((this.flags & NEW_AREA) != 0 && leadingSpace != null); }
Returns:true if first area is set
/** @return true if first area is set */
public boolean isFirstArea() { return ((this.flags & FIRST_AREA) != 0); }
Returns:true if last area is set
/** @return true if last area is set */
public boolean isLastArea() { return ((this.flags & LAST_AREA) != 0); }
Returns:true if suppress break before is set
/** @return true if suppress break before is set */
public boolean suppressBreakBefore() { return ((this.flags & SUPPRESS_BREAK_BEFORE) != 0); }
Returns the strength of a keep-with-next currently pending.
Returns:the keep-with-next strength
/** * Returns the strength of a keep-with-next currently pending. * @return the keep-with-next strength */
public Keep getKeepWithNextPending() { return this.pendingKeepWithNext; }
Returns the strength of a keep-with-previous currently pending.
Returns:the keep-with-previous strength
/** * Returns the strength of a keep-with-previous currently pending. * @return the keep-with-previous strength */
public Keep getKeepWithPreviousPending() { return this.pendingKeepWithPrevious; }
Clears any pending keep-with-next strength.
/** * Clears any pending keep-with-next strength. */
public void clearKeepWithNextPending() { this.pendingKeepWithNext = Keep.KEEP_AUTO; }
Clears any pending keep-with-previous strength.
/** * Clears any pending keep-with-previous strength. */
public void clearKeepWithPreviousPending() { this.pendingKeepWithPrevious = Keep.KEEP_AUTO; }
Clears both keep-with-previous and keep-with-next strengths.
/** * Clears both keep-with-previous and keep-with-next strengths. */
public void clearKeepsPending() { clearKeepWithPreviousPending(); clearKeepWithNextPending(); }
Updates the currently pending keep-with-next strength.
Params:
  • keep – the new strength to consider
/** * Updates the currently pending keep-with-next strength. * @param keep the new strength to consider */
public void updateKeepWithNextPending(Keep keep) { this.pendingKeepWithNext = this.pendingKeepWithNext.compare(keep); }
Updates the currently pending keep-with-previous strength.
Params:
  • keep – the new strength to consider
/** * Updates the currently pending keep-with-previous strength. * @param keep the new strength to consider */
public void updateKeepWithPreviousPending(Keep keep) { this.pendingKeepWithPrevious = this.pendingKeepWithPrevious.compare(keep); }
Indicates whether a keep-with-next constraint is pending.
Returns:true if a keep-with-next constraint is pending
/** * Indicates whether a keep-with-next constraint is pending. * @return true if a keep-with-next constraint is pending */
public boolean isKeepWithNextPending() { return !getKeepWithNextPending().isAuto(); }
Indicates whether a keep-with-previous constraint is pending.
Returns:true if a keep-with-previous constraint is pending
/** * Indicates whether a keep-with-previous constraint is pending. * @return true if a keep-with-previous constraint is pending */
public boolean isKeepWithPreviousPending() { return !getKeepWithPreviousPending().isAuto(); }
Params:
  • space – leading space
/** @param space leading space */
public void setLeadingSpace(SpaceSpecifier space) { leadingSpace = space; }
Returns:leading space
/** @return leading space */
public SpaceSpecifier getLeadingSpace() { return leadingSpace; }
Returns:true if resolve leading space is set
/** @return true if resolve leading space is set */
public boolean resolveLeadingSpace() { return ((this.flags & RESOLVE_LEADING_SPACE) != 0); }
Params:
  • space – trailing space
/** @param space trailing space */
public void setTrailingSpace(SpaceSpecifier space) { trailingSpace = space; }
Returns:trailing space
/** @return trailing space */
public SpaceSpecifier getTrailingSpace() { return trailingSpace; }
Adds a border or padding element to the pending list which will be used to generate the right element list for break possibilities. Conditionality resolution will be done elsewhere.
Params:
  • element – the border, padding or space element
/** * Adds a border or padding element to the pending list which will be used to generate * the right element list for break possibilities. Conditionality resolution will be done * elsewhere. * @param element the border, padding or space element */
public void addPendingAfterMark(UnresolvedListElementWithLength element) { if (this.pendingAfterMarks == null) { this.pendingAfterMarks = new java.util.ArrayList(); } this.pendingAfterMarks.add(element); }
See Also:
Returns:the pending border and padding elements at the after edge
/** * @return the pending border and padding elements at the after edge * @see #addPendingAfterMark(UnresolvedListElementWithLength) */
public List getPendingAfterMarks() { if (this.pendingAfterMarks != null) { return Collections.unmodifiableList(this.pendingAfterMarks); } else { return null; } }
Clears all pending marks on the LayoutContext.
/** * Clears all pending marks on the LayoutContext. */
public void clearPendingMarks() { this.pendingBeforeMarks = null; this.pendingAfterMarks = null; }
Adds a border or padding element to the pending list which will be used to generate the right element list for break possibilities. Conditionality resolution will be done elsewhere.
Params:
  • element – the border, padding or space element
/** * Adds a border or padding element to the pending list which will be used to generate * the right element list for break possibilities. Conditionality resolution will be done * elsewhere. * @param element the border, padding or space element */
public void addPendingBeforeMark(UnresolvedListElementWithLength element) { if (this.pendingBeforeMarks == null) { this.pendingBeforeMarks = new java.util.ArrayList(); } this.pendingBeforeMarks.add(element); }
See Also:
Returns:the pending border and padding elements at the before edge
/** * @return the pending border and padding elements at the before edge * @see #addPendingBeforeMark(UnresolvedListElementWithLength) */
public List getPendingBeforeMarks() { if (this.pendingBeforeMarks != null) { return Collections.unmodifiableList(this.pendingBeforeMarks); } else { return null; } }
Sets the stack limit in block-progression-dimension.
Params:
  • limit – the stack limit
/** * Sets the stack limit in block-progression-dimension. * @param limit the stack limit */
public void setStackLimitBP(MinOptMax limit) { stackLimitBP = limit; }
Returns the stack limit in block-progression-dimension.
Returns:the stack limit
/** * Returns the stack limit in block-progression-dimension. * @return the stack limit */
public MinOptMax getStackLimitBP() { return stackLimitBP; }
Sets the inline-progression-dimension of the nearest ancestor reference area.
Params:
  • ipd – of nearest ancestor reference area
/** * Sets the inline-progression-dimension of the nearest ancestor reference area. * @param ipd of nearest ancestor reference area */
public void setRefIPD(int ipd) { refIPD = ipd; }
Returns the inline-progression-dimension of the nearest ancestor reference area.
Returns:the inline-progression-dimension of the nearest ancestor reference area
/** * Returns the inline-progression-dimension of the nearest ancestor reference area. * * @return the inline-progression-dimension of the nearest ancestor reference area */
public int getRefIPD() { return refIPD; }
Params:
  • hyph – a hyphenation context
/** @param hyph a hyphenation context */
public void setHyphContext(HyphContext hyph) { hyphContext = hyph; }
Returns:hyphenation context
/** @return hyphenation context */
public HyphContext getHyphContext() { return hyphContext; }
Sets the currently applicable alignment in BP direction.
Params:
  • alignment – one of EN_START, EN_JUSTIFY etc.
/** * Sets the currently applicable alignment in BP direction. * @param alignment one of EN_START, EN_JUSTIFY etc. */
public void setBPAlignment(int alignment) { this.bpAlignment = alignment; }
Returns:the currently applicable alignment in BP direction (EN_START, EN_JUSTIFY...)
/** @return the currently applicable alignment in BP direction (EN_START, EN_JUSTIFY...) */
public int getBPAlignment() { return this.bpAlignment; }
Params:
  • adjust – space adjustment
/** @param adjust space adjustment */
public void setSpaceAdjust(double adjust) { dSpaceAdjust = adjust; }
Returns:space adjustment
/** @return space adjustment */
public double getSpaceAdjust() { return dSpaceAdjust; }
Params:
  • ipdA – ipd adjustment
/** @param ipdA ipd adjustment */
public void setIPDAdjust(double ipdA) { ipdAdjust = ipdA; }
Returns:ipd adjustment
/** @return ipd adjustment */
public double getIPDAdjust() { return ipdAdjust; }
Params:
  • alignmentContext – alignment context
/** @param alignmentContext alignment context */
public void setAlignmentContext(AlignmentContext alignmentContext) { this.alignmentContext = alignmentContext; }
Returns:alignment context
/** @return alignment context */
public AlignmentContext getAlignmentContext() { return this.alignmentContext; }
Reset alignment context.
/** * Reset alignment context. */
public void resetAlignmentContext() { if (this.alignmentContext != null) { this.alignmentContext = this.alignmentContext.getParentAlignmentContext(); } }
Get the width to be reserved for border and padding at the start of the line.
Returns:the width to be reserved
/** * Get the width to be reserved for border and padding at the start of the line. * @return the width to be reserved */
public int getLineStartBorderAndPaddingWidth() { return lineStartBorderAndPaddingWidth; }
Set the width to be reserved for border and padding at the start of the line.
Params:
  • lineStartBorderAndPaddingWidth – the width to be reserved
/** * Set the width to be reserved for border and padding at the start of the line. * @param lineStartBorderAndPaddingWidth the width to be reserved */
public void setLineStartBorderAndPaddingWidth(int lineStartBorderAndPaddingWidth) { this.lineStartBorderAndPaddingWidth = lineStartBorderAndPaddingWidth; }
Get the width to be reserved for border and padding at the end of the line.
Returns:the width to be reserved
/** * Get the width to be reserved for border and padding at the end of the line. * @return the width to be reserved */
public int getLineEndBorderAndPaddingWidth() { return lineEndBorderAndPaddingWidth; }
Set the width to be reserved for border and padding at the end of the line.
Params:
  • lineEndBorderAndPaddingWidth – the width to be reserved
/** * Set the width to be reserved for border and padding at the end of the line. * @param lineEndBorderAndPaddingWidth the width to be reserved */
public void setLineEndBorderAndPaddingWidth(int lineEndBorderAndPaddingWidth) { this.lineEndBorderAndPaddingWidth = lineEndBorderAndPaddingWidth; }
Returns:one of: Constants.NOT_SET, Constants.EN_NONE Constants.EN_ALL
/** * @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE} * {@link Constants#EN_ALL} */
public int getNextSpan() { return nextSpan; }
Returns:one of: Constants.NOT_SET, Constants.EN_NONE Constants.EN_ALL
/** * @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE} * {@link Constants#EN_ALL} */
public int getCurrentSpan() { return (currentSpan == Constants.NOT_SET) ? Constants.EN_NONE : currentSpan; }
Used to signal the PSLM that the element list ends early because of a span change in multi-column layout.
Params:
  • span – the new span value (legal values: NOT_SET, EN_NONE, EN_ALL)
/** * Used to signal the PSLM that the element list ends early because of a span change in * multi-column layout. * @param span the new span value (legal values: NOT_SET, EN_NONE, EN_ALL) */
public void signalSpanChange(int span) { switch (span) { case Constants.NOT_SET: case Constants.EN_NONE: case Constants.EN_ALL: this.currentSpan = this.nextSpan; this.nextSpan = span; break; default: assert false; throw new IllegalArgumentException("Illegal value on signalSpanChange() for span: " + span); } }
Get the writing mode of the relevant reference area.
Returns:the applicable writing mode
/** * Get the writing mode of the relevant reference area. * @return the applicable writing mode */
public WritingMode getWritingMode() { return writingMode; }
Set the writing mode.
Params:
  • writingMode – the writing mode
/** * Set the writing mode. * @param writingMode the writing mode */
public void setWritingMode(WritingMode writingMode) { this.writingMode = writingMode; }
Get the current amount of space before / start
Returns:the space before / start amount
/** * Get the current amount of space before / start * @return the space before / start amount */
public int getSpaceBefore() { return spaceBefore; }
Set the amount of space before / start
Params:
  • spaceBefore – the amount of space before / start
/** * Set the amount of space before / start * @param spaceBefore the amount of space before / start */
public void setSpaceBefore(int spaceBefore) { this.spaceBefore = spaceBefore; }
Get the current amount of space after / end
Returns:the space after / end amount
/** * Get the current amount of space after / end * @return the space after / end amount */
public int getSpaceAfter() { return spaceAfter; }
Set the amount of space after / end
Params:
  • spaceAfter – the amount of space after / end
/** * Set the amount of space after / end * @param spaceAfter the amount of space after / end */
public void setSpaceAfter(int spaceAfter) { this.spaceAfter = spaceAfter; }
Returns the value of the break before the element whose LayoutManager.getNextKnuthElements(LayoutContext, int) method has just been called.
Returns:one of Constants.EN_AUTO, Constants.EN_COLUMN, Constants.EN_PAGE, Constants.EN_EVEN_PAGE, or Constants.EN_ODD_PAGE
/** * Returns the value of the break before the element whose * {@link LayoutManager#getNextKnuthElements(LayoutContext, int)} method has just been * called. * * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or * {@link Constants#EN_ODD_PAGE} */
public int getBreakBefore() { return breakBefore; }
Sets the value of the break before the current element.
Params:
  • breakBefore – the value of the break-before
See Also:
/** * Sets the value of the break before the current element. * * @param breakBefore the value of the break-before * @see #getBreakBefore() */
public void setBreakBefore(int breakBefore) { this.breakBefore = breakBefore; }
Returns the value of the break after the element whose LayoutManager.getNextKnuthElements(LayoutContext, int) method has just been called.
Returns:one of Constants.EN_AUTO, Constants.EN_COLUMN, Constants.EN_PAGE, Constants.EN_EVEN_PAGE, or Constants.EN_ODD_PAGE
/** * Returns the value of the break after the element whose * {@link LayoutManager#getNextKnuthElements(LayoutContext, int)} method has just been * called. * * @return one of {@link Constants#EN_AUTO}, {@link Constants#EN_COLUMN}, * {@link Constants#EN_PAGE}, {@link Constants#EN_EVEN_PAGE}, or * {@link Constants#EN_ODD_PAGE} */
public int getBreakAfter() { return breakAfter; }
Sets the value of the break after the current element.
Params:
  • breakAfter – the value of the break-after
See Also:
/** * Sets the value of the break after the current element. * * @param breakAfter the value of the break-after * @see #getBreakAfter() */
public void setBreakAfter(int breakAfter) { this.breakAfter = breakAfter; }
{@inheritDoc}
/** {@inheritDoc} */
@Override public String toString() { return "Layout Context:" + "\nStack Limit BPD: \t" + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString()) + "\nTrailing Space: \t" + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) + "\nLeading Space: \t" + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString()) + "\nReference IPD: \t" + getRefIPD() + "\nSpace Adjust: \t" + getSpaceAdjust() + "\nIPD Adjust: \t" + getIPDAdjust() + "\nResolve Leading Space: \t" + resolveLeadingSpace() + "\nSuppress Break Before: \t" + suppressBreakBefore() + "\nIs First Area: \t" + isFirstArea() + "\nStarts New Area: \t" + startsNewArea() + "\nIs Last Area: \t" + isLastArea() + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending() + "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending" + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" + (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]"; }
Returns whether the column balancer should be disabled before a spanning block
Returns:one of Constants.EN_TRUE, Constants.EN_FALSE
/** * Returns whether the column balancer should be disabled before a spanning block * * @return one of {@link Constants#EN_TRUE}, {@link Constants#EN_FALSE} */
public int getDisableColumnBalancing() { return disableColumnBalancing; }
Sets whether the column balancer should be disabled before a spanning block
Params:
  • disableColumnBalancing – the value of the fox:disable-column-balancing property
See Also:
/** * Sets whether the column balancer should be disabled before a spanning block * * @param disableColumnBalancing the value of the fox:disable-column-balancing property * @see #getDisableColumnBalancing() */
public void setDisableColumnBalancing(int disableColumnBalancing) { this.disableColumnBalancing = disableColumnBalancing; } public boolean treatAsArtifact() { return (flags & TREAT_AS_ARTIFACT) != 0; } public void setTreatAsArtifact(boolean treatAsArtifact) { setFlags(TREAT_AS_ARTIFACT, treatAsArtifact); } }