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

org.openide.util.MapFormat Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * 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.
 */
package org.openide.util;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.text.ParsePosition;

import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;


/** 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; /** Array with to-be-skipped blocks */ //private RangeList skipped; static final long serialVersionUID = -7695811542873819435L; /** 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; /** * 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; int 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; int 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; if (key.length() > 0) { obj = formatObject(processKey(key)); } else { // else just copy the left and right braces result.append(this.ldel); result.append(this.rdel); continue; } 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 = 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(); } } */ }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy