alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.util;

import java.util.Map;
import java.util.Locale;
import java.util.Date;
import java.util.Iterator;
import java.text.Format;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.MessageFormat;

/** A text format similar to MessageFormat
 * but using string rather than numeric keys.
 * You might use use this formatter like this:
 * 
MapFormat.format("Hello {name}", map);
* Or to have more control over it: *
 * Map m = new HashMap ();
 * m.put ("KEY", "value");
 * MapFormat f = new MapFormat (m);
 * f.setLeftBrace ("__");
 * f.setRightBrace ("__");
 * String result = f.format ("the __KEY__ here");
 * 
* * @author Slavek Psenicka * @see MessageFormat */ public class MapFormat extends Format { private static final int BUFSIZE = 255; /** Locale region settings used for number and date formatting */ private Locale locale = Locale.getDefault(); /** Left delimiter */ private String ldel = "{"; // NOI18N /** Right delimiter */ private String rdel = "}"; // NOI18N /** Used formatting map */ private Map argmap; /** Offsets to {} expressions */ private int[] offsets; /** Keys enclosed by {} brackets */ private String[] arguments; /** Max used offset */ private int maxOffset; /** Should be thrown an exception if key was not found? */ private boolean throwex = false; /** Exactly match brackets? */ private boolean exactmatch = true; /** Array with to-be-skipped blocks */ //private RangeList skipped; static final long serialVersionUID =-7695811542873819435L; /** * Constructor. * For common work use format(pattern, arguments) . * @param arguments keys and values to use in the format */ public MapFormat(Map arguments) { super(); setMap(arguments); } /** * Designated method. It gets the string, initializes HashFormat object * and returns converted string. It scans pattern * for {} brackets, then parses enclosed string and replaces it * with argument's get() value. * @param pattern String to be parsed. * @param arguments Map with key-value pairs to replace. * @return Formatted string */ public static String format(String pattern, Map arguments) { MapFormat temp = new MapFormat(arguments); return temp.format(pattern); } // unused so removed --jglick /** * Search for comments and quotation marks. * Prepares internal structures. * @param pattern String to be parsed. * @param lmark Left mark of to-be-skipped block. * @param rmark Right mark of to-be-skipped block or null if does not exist (// comment). private void process(String pattern, String lmark, String rmark) { int idx = 0; while (true) { int ridx = -1, lidx = pattern.indexOf(lmark,idx); if (lidx >= 0) { if (rmark != null) { ridx = pattern.indexOf(rmark,lidx + lmark.length()); } else ridx = pattern.length(); } else break; if (ridx >= 0) { skipped.put(new Range(lidx, ridx-lidx)); if (rmark != null) idx = ridx+rmark.length(); else break; } else break; } } */ /** Returns the value for given key. Subclass may define its own beahvior of * this method. For example, if key is not defined, subclass can return * string. * * @param key Key. * @return Value for this key. */ protected Object processKey(String key) { return argmap.get(key); } /** * Scans the pattern and prepares internal variables. * @param newPattern String to be parsed. * @exception IllegalArgumentException if number of arguments exceeds BUFSIZE or * parser found unmatched brackets (this exception should be switched off * using setExactMatch(false)). */ public String processPattern(String newPattern) throws IllegalArgumentException { int idx = 0, offnum = -1; StringBuffer outpat = new StringBuffer(); offsets = new int[BUFSIZE]; arguments = new String[BUFSIZE]; maxOffset = -1; //skipped = new RangeList(); // What was this for?? //process(newPattern, "\"", "\""); // NOI18N while (true) { int ridx = -1, lidx = newPattern.indexOf(ldel,idx); /* Range ran = skipped.getRangeContainingOffset(lidx); if (ran != null) { outpat.append(newPattern.substring(idx, ran.getEnd())); idx = ran.getEnd(); continue; } */ if (lidx >= 0) { ridx = newPattern.indexOf(rdel,lidx + ldel.length()); } else break; if (++offnum >= BUFSIZE) throw new IllegalArgumentException(NbBundle.getBundle(MapFormat.class).getString("MSG_TooManyArguments")); if (ridx < 0) { if (exactmatch) throw new IllegalArgumentException(NbBundle.getBundle(MapFormat.class).getString("MSG_UnmatchedBraces") +" "+lidx); else break; } outpat.append(newPattern.substring(idx, lidx)); offsets[offnum] = outpat.length(); arguments[offnum] = newPattern.substring(lidx + ldel.length(), ridx); idx = ridx + rdel.length(); maxOffset++; } outpat.append(newPattern.substring(idx)); return outpat.toString(); } /** * Formats object. * @param obj Object to be formatted into string * @return Formatted object */ private String formatObject(Object obj) { if (obj == null) return null; if (obj instanceof Number) { return NumberFormat.getInstance(locale).format(obj); // fix } else if (obj instanceof Date) { return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale).format(obj);//fix } else if (obj instanceof String) return (String)obj; return obj.toString(); } /** * Formats the parsed string by inserting table's values. * @param pat a string pattern * @param result Buffer to be used for result. * @param fpos position * @return Formatted string */ public StringBuffer format(Object pat, StringBuffer result, FieldPosition fpos) { String pattern = processPattern((String)pat); int lastOffset = 0; for (int i = 0; i <= maxOffset; ++i) { int offidx = offsets[i]; result.append(pattern.substring(lastOffset, offsets[i])); lastOffset = offidx; String key = arguments[i]; String obj = formatObject(processKey(key)); if (obj == null) { // try less-greedy match; useful for e.g. PROP___PROPNAME__ where // 'PROPNAME' is a key and delims are both '__' // this does not solve all possible cases, surely, but it should catch // the most common ones String lessgreedy = ldel + key; int fromright = lessgreedy.lastIndexOf (ldel); if (fromright > 0) { String newkey = lessgreedy.substring (fromright + ldel.length ()); String newsubst = formatObject (processKey (newkey)); if (newsubst != null) obj = lessgreedy.substring (0, fromright) + newsubst; } } if (obj == null) { if (throwex) throw new IllegalArgumentException(MessageFormat.format(NbBundle.getBundle(MapFormat.class).getString("MSG_FMT_ObjectForKey"), new Object [] {new Integer (key)})); else obj = ldel+key+rdel; } result.append(obj); } result.append(pattern.substring(lastOffset, pattern.length())); return result; } /** * Parses the string. Does not yet handle recursion (where * the substituted strings contain %n references.) */ public Object parseObject (String text, ParsePosition status) { return parse(text); } /** * Parses the string. Does not yet handle recursion (where * the substituted strings contain {n} references.) * @return New format. */ public String parse(String source) { StringBuffer sbuf = new StringBuffer(source); Iterator key_it = argmap.keySet().iterator(); //skipped = new RangeList(); // What was this for?? //process(source, "\"", "\""); // NOI18N while (key_it.hasNext()) { String it_key = (String)key_it.next(); String it_obj = formatObject(argmap.get(it_key)); int it_idx = -1; do { it_idx = sbuf.toString().indexOf(it_obj, ++it_idx); if (it_idx >= 0/* && !skipped.containsOffset(it_idx) */) { sbuf.replace(it_idx, it_idx+it_obj.length(), ldel+it_key+rdel); //skipped = new RangeList(); // What was this for?? //process(sbuf.toString(), "\"", "\""); // NOI18N } } while (it_idx != -1); } return sbuf.toString(); } /** Test whether formatter will throw exception if object for key was not found. * If given map does not contain object for key specified, it could * throw an exception. Returns true if throws. If not, key is left unchanged. */ public boolean willThrowExceptionIfKeyWasNotFound() { return throwex; } /** Specify whether formatter will throw exception if object for key was not found. * If given map does not contain object for key specified, it could * throw an exception. If does not throw, key is left unchanged. * @param flag If true, formatter throws IllegalArgumentException. */ public void setThrowExceptionIfKeyWasNotFound(boolean flag) { throwex = flag; } /** Test whether both brackets are required in the expression. * If not, use setExactMatch(false) and formatter will ignore missing right * bracket. Advanced feature. */ public boolean isExactMatch() { return exactmatch; } /** Specify whether both brackets are required in the expression. * If not, use setExactMatch(false) and formatter will ignore missing right * bracket. Advanced feature. * @param flag If true, formatter will ignore missing right bracket (default = false) */ public void setExactMatch(boolean flag) { exactmatch = flag; } /** Returns string used as left brace */ public String getLeftBrace() { return ldel; } /** Sets string used as left brace * @param delimiter Left brace. */ public void setLeftBrace(String delimiter) { ldel = delimiter; } /** Returns string used as right brace */ public String getRightBrace() { return rdel; } /** Sets string used as right brace * @param delimiter Right brace. */ public void setRightBrace(String delimiter) { rdel = delimiter; } /** Returns argument map */ public Map getMap() { return argmap; } /** Sets argument map * This map should contain key-value pairs with key values used in * formatted string expression. If value for key was not found, formatter leave * key unchanged (except if you've set setThrowExceptionIfKeyWasNotFound(true), * then it fires IllegalArgumentException. * * @param map the argument map */ public void setMap(Map map) { argmap = map; } // commented out because unused --jglick /** * Range of expression in string. * Used internally to store information about quotation marks and comments * in formatted string. * * @author Slavek Psenicka * @version 1.0, March 11. 1999 * class Range extends Object { /** Offset of expression * private int offset; /** Length of expression * private int length; /** Constructor * public Range(int off, int len) { offset = off; length = len; } /** Returns offset * public int getOffset() { return offset; } /** Returns length of expression * public int getLength() { return length; } /** Returns final position of expression * public int getEnd() { return offset+length; } public String toString() { return "("+offset+", "+length+")"; // NOI18N } } /** * List of ranges. * Used internally to store information about quotation marks and comments * in formatted string. * * @author Slavek Psenicka * @version 1.0, March 11. 1999 * class RangeList { /** Map with Ranges * private HashMap hmap; /** Constructor * public RangeList() { hmap = new HashMap(); } /** Returns true if offset is enclosed by any Range object in list * public boolean containsOffset(int offset) { return (getRangeContainingOffset(offset) != null); } /** Returns enclosing Range object in list for given offset * public Range getRangeContainingOffset(int offset) { if (hmap.size() == 0) return null; int offit = offset; while (offit-- >= 0) { Integer off = new Integer(offit); if (hmap.containsKey(off)) { Range ran = (Range)hmap.get(off); if (ran.getEnd() - offset > 0) return ran; } } return null; } /** Puts new range into list * public void put(Range range) { hmap.put(new Integer(range.getOffset()), range); } public String toString() { return hmap.toString(); } } */ }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.