Missing warning for unknown formatting objects added. Warning is not issued by the ElementMappingRegistry anymore but by FOTreeBuilder which has access to more context information. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_ProcessingFeedback@642975 13f79535-47bb-0310-9956-ffa450edef68Temp_ProcessingFeedback
@@ -1,4 +1,6 @@ | |||
org.apache.fop.util.text.IfFieldPart$Factory | |||
org.apache.fop.util.text.EqualsFieldPart$Factory | |||
org.apache.fop.util.text.ChoiceFieldPart$Factory | |||
org.apache.fop.util.text.HexFieldPart$Factory | |||
org.apache.fop.util.text.GlyphNameFieldPart$Factory | |||
org.apache.fop.events.EventFormatter$LookupFieldPartFactory |
@@ -51,6 +51,7 @@ Any reference to it will be considered a reference to the first occurrence in th | |||
<message key="org.apache.fop.fo.FOValidationEventProducer.columnCountErrorOnRegionBodyOverflowScroll">If overflow property is set to "scroll" on {elementName}, a column-count other than "1" may not be specified.{{locator}}</message> | |||
<message key="org.apache.fop.fo.FOValidationEventProducer.invalidFORoot">First element must be the fo:root formatting object. Found {elementName} instead. Please make sure you're producing a valid XSL-FO document.</message> | |||
<message key="org.apache.fop.fo.FOValidationEventProducer.emptyDocument">Document is empty (something might be wrong with your XSLT stylesheet).</message> | |||
<message key="org.apache.fop.fo.FOValidationEventProducer.unknownFormattingObject">Unknown formatting object "{offendingNode}" encountered (a child of {elementName}}.{{locator}}</message> | |||
<message key="org.apache.fop.fo.flow.table.TableEventProducer.nonAutoBPDOnTable">Only a value of "auto" for block-progression-dimension has a well-specified behavior on fo:table. Falling back to "auto".{{locator}}</message> | |||
<message key="org.apache.fop.fo.flow.table.TableEventProducer.noTablePaddingWithCollapsingBorderModel">In collapsing border model a table does not have padding (see http://www.w3.org/TR/REC-CSS2/tables.html#collapsing-borders), but a non-zero value for padding was found. The padding will be ignored.{{locator}}</message> | |||
<message key="org.apache.fop.fo.flow.table.TableEventProducer.noMixRowsAndCells">Either fo:table-rows or fo:table-cells may be children of an {elementName} but not both.{{locator}}</message> | |||
@@ -94,4 +95,7 @@ Any reference to it will be considered a reference to the first occurrence in th | |||
<message key="org.apache.fop.area.AreaEventProducer.pageLoadError">Error while deserializing page {page}.[ Reason: {e}]</message> | |||
<message key="org.apache.fop.area.AreaEventProducer.pageSaveError">Error while serializing page {page}.[ Reason: {e}]</message> | |||
<message key="org.apache.fop.area.AreaEventProducer.pageRenderingError">Error while rendering page {page}.[ Reason: {e}]</message> | |||
<message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message> | |||
<message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message> | |||
<message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> | |||
</catalogue> |
@@ -23,6 +23,7 @@ import java.util.Iterator; | |||
import java.util.Map; | |||
import org.w3c.dom.DOMImplementation; | |||
import org.xml.sax.Locator; | |||
import org.apache.commons.logging.Log; | |||
@@ -144,7 +145,6 @@ public class ElementMappingRegistry { | |||
+ "No element mapping definition found for " | |||
+ FONode.getNodeString(namespaceURI, localName), locator); | |||
} else { | |||
log.warn("Unknown formatting object " + namespaceURI + "^" + localName); | |||
fobjMaker = new UnknownXMLObj.Maker(namespaceURI); | |||
} | |||
} |
@@ -48,6 +48,7 @@ import org.apache.fop.fo.flow.table.TableColumn; | |||
import org.apache.fop.fo.flow.table.TableRow; | |||
import org.apache.fop.fo.pagination.Flow; | |||
import org.apache.fop.fo.pagination.PageSequence; | |||
import org.apache.fop.fonts.FontEventAdapter; | |||
import org.apache.fop.fonts.FontInfo; | |||
/** | |||
@@ -101,6 +102,7 @@ public abstract class FOEventHandler { | |||
public FOEventHandler(FOUserAgent foUserAgent) { | |||
this.foUserAgent = foUserAgent; | |||
this.fontInfo = new FontInfo(); | |||
this.fontInfo.setEventListener(new FontEventAdapter(foUserAgent.getEventBroadcaster())); | |||
} | |||
/** |
@@ -31,6 +31,8 @@ import org.xml.sax.helpers.DefaultHandler; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.xmlgraphics.util.QName; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.apps.FOUserAgent; | |||
import org.apache.fop.apps.FormattingResults; | |||
@@ -181,18 +183,6 @@ public class FOTreeBuilder extends DefaultHandler { | |||
} | |||
} | |||
/** | |||
* Finds the {@link Maker} used to create {@link FONode} objects of a particular type | |||
* | |||
* @param namespaceURI URI for the namespace of the element | |||
* @param localName name of the Element | |||
* @return the ElementMapping.Maker that can create an FO object for this element | |||
* @throws FOPException if a Maker could not be found for a bound namespace. | |||
*/ | |||
private Maker findFOMaker(String namespaceURI, String localName) throws FOPException { | |||
return elementMappingRegistry.findFOMaker(namespaceURI, localName, locator); | |||
} | |||
/** {@inheritDoc} */ | |||
public void warning(SAXParseException e) { | |||
log.warn(e.getLocalizedMessage()); | |||
@@ -374,7 +364,29 @@ public class FOTreeBuilder extends DefaultHandler { | |||
/** {@inheritDoc} */ | |||
public void endDocument() throws SAXException { | |||
currentFObj = null; | |||
} | |||
} | |||
/** | |||
* Finds the {@link Maker} used to create {@link FONode} objects of a particular type | |||
* | |||
* @param namespaceURI URI for the namespace of the element | |||
* @param localName name of the Element | |||
* @return the ElementMapping.Maker that can create an FO object for this element | |||
* @throws FOPException if a Maker could not be found for a bound namespace. | |||
*/ | |||
private Maker findFOMaker(String namespaceURI, String localName) throws FOPException { | |||
Maker maker = elementMappingRegistry.findFOMaker(namespaceURI, localName, locator); | |||
if (maker instanceof UnknownXMLObj.Maker) { | |||
FOValidationEventProducer eventProducer | |||
= FOValidationEventProducer.Factory.create( | |||
foEventHandler.getUserAgent().getEventBroadcaster()); | |||
eventProducer.unknownFormattingObject(this, currentFObj.getName(), | |||
new QName(namespaceURI, localName), | |||
getEffectiveLocator()); | |||
} | |||
return maker; | |||
} | |||
} | |||
} | |||
@@ -333,5 +333,16 @@ public interface FOValidationEventProducer extends EventProducer { | |||
* @event.severity FATAL | |||
*/ | |||
void emptyDocument(Object source) throws ValidationException; | |||
/** | |||
* An unknown/unsupported formatting object has been encountered. | |||
* @param source the event source | |||
* @param elementName the name of the context node | |||
* @param offendingNode the offending node | |||
* @param loc the location of the error or null | |||
* @event.severity WARN | |||
*/ | |||
void unknownFormattingObject(Object source, String elementName, | |||
QName offendingNode, Locator loc); | |||
} |
@@ -0,0 +1,82 @@ | |||
/* | |||
* 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$ */ | |||
package org.apache.fop.fonts; | |||
import java.util.Map; | |||
import org.apache.fop.events.Event; | |||
import org.apache.fop.events.EventBroadcaster; | |||
import org.apache.fop.events.model.EventSeverity; | |||
/** | |||
* Event listener interface for font-related events. This interface extends FontEventListener | |||
* and EventProducer for integration into FOP's event subsystem. | |||
*/ | |||
public class FontEventAdapter implements FontEventListener { | |||
private EventBroadcaster eventBroadcaster; | |||
/** | |||
* Creates a new FontEventAdapter. | |||
* @param broadcaster the event broadcaster to send the generated events to | |||
*/ | |||
public FontEventAdapter(EventBroadcaster broadcaster) { | |||
this.eventBroadcaster = broadcaster; | |||
} | |||
/** | |||
* Returns the event group ID. | |||
* @return the event group ID | |||
*/ | |||
protected String getEventGroupID() { | |||
return getClass().getName(); | |||
} | |||
/** {@inheritDoc} */ | |||
public void fontSubstituted(Object source, FontTriplet requested, FontTriplet effective) { | |||
Map params = new java.util.HashMap(); | |||
params.put("requested", requested); | |||
params.put("effective", effective); | |||
Event ev = new Event(source, getEventGroupID() + ".fontSubstituted", | |||
EventSeverity.WARN, params); | |||
this.eventBroadcaster.broadcastEvent(ev); | |||
} | |||
/** {@inheritDoc} */ | |||
public void fontLoadingErrorAtAutoDetection(Object source, String fontURL, Exception e) { | |||
Map params = new java.util.HashMap(); | |||
params.put("fontURL", fontURL); | |||
params.put("e", e); | |||
Event ev = new Event(source, getEventGroupID() + ".fontLoadingErrorAtAutoDetection", | |||
EventSeverity.WARN, params); | |||
this.eventBroadcaster.broadcastEvent(ev); | |||
} | |||
/** {@inheritDoc} */ | |||
public void glyphNotAvailable(Object source, char ch, String fontName) { | |||
Map params = new java.util.HashMap(); | |||
params.put("ch", new Character(ch)); | |||
params.put("fontName", fontName); | |||
Event ev = new Event(source, getEventGroupID() + ".glyphNotAvailable", | |||
EventSeverity.WARN, params); | |||
this.eventBroadcaster.broadcastEvent(ev); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
/* | |||
* 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$ */ | |||
package org.apache.fop.fonts; | |||
/** | |||
* Event listener interface for font-related events. | |||
*/ | |||
public interface FontEventListener { | |||
/** | |||
* Notifies about a font being substituted as the requested one isn't available. | |||
* @param source the event source | |||
* @param requested the requested font triplet | |||
* @param effective the effective font triplet | |||
*/ | |||
void fontSubstituted(Object source, FontTriplet requested, FontTriplet effective); | |||
/** | |||
* An error occurred while loading a font for auto-detection. | |||
* @param source the event source | |||
* @param fontURL the font URL | |||
* @param e the original exception | |||
*/ | |||
void fontLoadingErrorAtAutoDetection(Object source, String fontURL, Exception e); | |||
/** | |||
* A glyph has been requested that is not available in the font. | |||
* @param source the event source | |||
* @param ch the character for which the glyph isn't available | |||
* @param fontName the name of the font | |||
*/ | |||
void glyphNotAvailable(Object source, char ch, String fontName); | |||
} |
@@ -67,6 +67,8 @@ public class FontInfo { | |||
/** Cache for Font instances. */ | |||
private Map fontInstanceCache = new java.util.HashMap(); | |||
private FontEventListener eventListener; | |||
/** | |||
* Main constructor | |||
*/ | |||
@@ -77,6 +79,15 @@ public class FontInfo { | |||
this.usedFonts = new java.util.HashMap(); | |||
} | |||
/** | |||
* Sets the font event listener that can be used to receive events about particular events | |||
* in this class. | |||
* @param listener the font event listener | |||
*/ | |||
public void setEventListener(FontEventListener listener) { | |||
this.eventListener = listener; | |||
} | |||
/** | |||
* Checks if the font setup is valid (At least the ultimate fallback font | |||
* must be registered.) | |||
@@ -158,6 +169,9 @@ public class FontInfo { | |||
public void addMetrics(String name, FontMetrics metrics) { | |||
// add the given metrics as a font with the given name | |||
if (metrics instanceof Typeface) { | |||
((Typeface)metrics).setEventListener(this.eventListener); | |||
} | |||
this.fonts.put(name, metrics); | |||
} | |||
@@ -364,8 +378,12 @@ public class FontInfo { | |||
} | |||
if (!loggedFontKeys.contains(replacedKey)) { | |||
loggedFontKeys.add(replacedKey); | |||
log.warn("Font '" + replacedKey + "' not found. " | |||
+ "Substituting with '" + newKey + "'."); | |||
if (this.eventListener != null) { | |||
this.eventListener.fontSubstituted(this, replacedKey, newKey); | |||
} else { | |||
log.warn("Font '" + replacedKey + "' not found. " | |||
+ "Substituting with '" + newKey + "'."); | |||
} | |||
} | |||
} | |||
@@ -139,6 +139,7 @@ public class LazyFont extends Typeface implements FontDescriptor { | |||
throw new RuntimeException(ioex.getMessage()); | |||
} | |||
} | |||
realFont.setEventListener(this.eventListener); | |||
isMetricsLoaded = true; | |||
} | |||
} |
@@ -117,18 +117,22 @@ public class SingleByteFont extends CustomFont { | |||
} | |||
//Give up, character is not available | |||
Character ch = new Character(c); | |||
if (warnedChars == null) { | |||
warnedChars = new java.util.HashSet(); | |||
} | |||
if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { | |||
warnedChars.add(ch); | |||
if (warnedChars.size() == 8) { | |||
log.warn("Many requested glyphs are not available in font " + getFontName()); | |||
} else { | |||
log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) | |||
+ ", " + Glyphs.charToGlyphName(c) | |||
+ ") not available in font " + getFontName()); | |||
if (this.eventListener != null) { | |||
this.eventListener.glyphNotAvailable(this, c, getFontName()); | |||
} else { | |||
Character ch = new Character(c); | |||
if (warnedChars == null) { | |||
warnedChars = new java.util.HashSet(); | |||
} | |||
if (warnedChars.size() < 8 && !warnedChars.contains(ch)) { | |||
warnedChars.add(ch); | |||
if (warnedChars.size() == 8) { | |||
log.warn("Many requested glyphs are not available in font " + getFontName()); | |||
} else { | |||
log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c) | |||
+ ", " + Glyphs.charToGlyphName(c) | |||
+ ") not available in font " + getFontName()); | |||
} | |||
} | |||
} | |||
return NOT_FOUND; |
@@ -30,6 +30,9 @@ public abstract class Typeface implements FontMetrics { | |||
*/ | |||
private long charMapOps = 0; | |||
/** An optional event listener that receives events such as missing glyphs etc. */ | |||
protected FontEventListener eventListener; | |||
/** | |||
* Get the encoding of the font. | |||
* @return the encoding | |||
@@ -80,5 +83,14 @@ public abstract class Typeface implements FontMetrics { | |||
return getAscender(size); | |||
} | |||
/** | |||
* Sets the font event listener that can be used to receive events about particular events | |||
* in this class. | |||
* @param listener the font event listener | |||
*/ | |||
public void setEventListener(FontEventListener listener) { | |||
this.eventListener = listener; | |||
} | |||
} | |||
@@ -37,6 +37,7 @@ import org.apache.fop.fonts.CustomFont; | |||
import org.apache.fop.fonts.EmbedFontInfo; | |||
import org.apache.fop.fonts.Font; | |||
import org.apache.fop.fonts.FontCache; | |||
import org.apache.fop.fonts.FontEventListener; | |||
import org.apache.fop.fonts.FontLoader; | |||
import org.apache.fop.fonts.FontResolver; | |||
import org.apache.fop.fonts.FontTriplet; | |||
@@ -50,6 +51,17 @@ public class FontInfoFinder { | |||
/** logging instance */ | |||
private Log log = LogFactory.getLog(FontInfoFinder.class); | |||
private FontEventListener eventListener; | |||
/** | |||
* Sets the font event listener that can be used to receive events about particular events | |||
* in this class. | |||
* @param listener the font event listener | |||
*/ | |||
public void setEventListener(FontEventListener listener) { | |||
this.eventListener = listener; | |||
} | |||
/** | |||
* Attempts to determine FontTriplets from a given CustomFont. | |||
* It seems to be fairly accurate but will probably require some tweaking over time | |||
@@ -189,15 +201,17 @@ public class FontInfoFinder { | |||
try { | |||
customFont = FontLoader.loadFont(fontUrl, resolver); | |||
} catch (Exception e) { | |||
//TODO Too verbose (it's an error but we don't care if some fonts can't be loaded) | |||
if (log.isErrorEnabled()) { | |||
log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage()); | |||
if (this.eventListener != null) { | |||
this.eventListener.fontLoadingErrorAtAutoDetection(this, embedUrl, e); | |||
} | |||
if (fontCache != null) { | |||
fontCache.registerFailedFont(embedUrl, fileLastModified); | |||
} | |||
return null; | |||
} | |||
if (this.eventListener != null) { | |||
customFont.setEventListener(this.eventListener); | |||
} | |||
return fontInfoFromCustomFont(fontUrl, customFont, fontCache); | |||
} | |||
} |
@@ -0,0 +1,89 @@ | |||
/* | |||
* 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$ */ | |||
package org.apache.fop.util.text; | |||
import java.util.Map; | |||
import org.apache.xmlgraphics.fonts.Glyphs; | |||
import org.apache.fop.util.text.AdvancedMessageFormat.Part; | |||
import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; | |||
/** | |||
* Function formatting a character to a glyph name. | |||
*/ | |||
public class GlyphNameFieldPart implements Part { | |||
private String fieldName; | |||
/** | |||
* Creates a new glyph name field part | |||
* @param fieldName the field name | |||
*/ | |||
public GlyphNameFieldPart(String fieldName) { | |||
this.fieldName = fieldName; | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean isGenerated(Map params) { | |||
Object obj = params.get(fieldName); | |||
return obj != null && getGlyphName(obj).length() > 0; | |||
} | |||
private String getGlyphName(Object obj) { | |||
if (obj instanceof Character) { | |||
return Glyphs.charToGlyphName(((Character)obj).charValue()); | |||
} else { | |||
throw new IllegalArgumentException( | |||
"Value for glyph name part must be a Character but was: " | |||
+ obj.getClass().getName()); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void write(StringBuffer sb, Map params) { | |||
if (!params.containsKey(fieldName)) { | |||
throw new IllegalArgumentException( | |||
"Message pattern contains unsupported field name: " + fieldName); | |||
} | |||
Object obj = params.get(fieldName); | |||
sb.append(getGlyphName(obj)); | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return "{" + this.fieldName + ",glyph-name}"; | |||
} | |||
/** Factory for {@link GlyphNameFieldPart}. */ | |||
public static class Factory implements PartFactory { | |||
/** {@inheritDoc} */ | |||
public Part newPart(String fieldName, String values) { | |||
return new GlyphNameFieldPart(fieldName); | |||
} | |||
/** {@inheritDoc} */ | |||
public String getFormat() { | |||
return "glyph-name"; | |||
} | |||
} | |||
} |
@@ -0,0 +1,84 @@ | |||
/* | |||
* 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$ */ | |||
package org.apache.fop.util.text; | |||
import java.util.Map; | |||
import org.apache.fop.util.text.AdvancedMessageFormat.Part; | |||
import org.apache.fop.util.text.AdvancedMessageFormat.PartFactory; | |||
/** | |||
* Function formatting a number or character to a hex value. | |||
*/ | |||
public class HexFieldPart implements Part { | |||
private String fieldName; | |||
/** | |||
* Creates a new hex field part | |||
* @param fieldName the field name | |||
*/ | |||
public HexFieldPart(String fieldName) { | |||
this.fieldName = fieldName; | |||
} | |||
/** {@inheritDoc} */ | |||
public boolean isGenerated(Map params) { | |||
Object obj = params.get(fieldName); | |||
return obj != null; | |||
} | |||
/** {@inheritDoc} */ | |||
public void write(StringBuffer sb, Map params) { | |||
if (!params.containsKey(fieldName)) { | |||
throw new IllegalArgumentException( | |||
"Message pattern contains unsupported field name: " + fieldName); | |||
} | |||
Object obj = params.get(fieldName); | |||
if (obj instanceof Character) { | |||
sb.append(Integer.toHexString(((Character)obj).charValue())); | |||
} else if (obj instanceof Number) { | |||
sb.append(Integer.toHexString(((Number)obj).intValue())); | |||
} else { | |||
throw new IllegalArgumentException("Incompatible value for hex field part: " | |||
+ obj.getClass().getName()); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public String toString() { | |||
return "{" + this.fieldName + ",hex}"; | |||
} | |||
/** Factory for {@link HexFieldPart}. */ | |||
public static class Factory implements PartFactory { | |||
/** {@inheritDoc} */ | |||
public Part newPart(String fieldName, String values) { | |||
return new HexFieldPart(fieldName); | |||
} | |||
/** {@inheritDoc} */ | |||
public String getFormat() { | |||
return "hex"; | |||
} | |||
} | |||
} |