/*********************************************************************************
* The contents of this file are subject to the Common Public Attribution
* License Version 1.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.openemm.org/cpal1.html. The License is based on the Mozilla
* Public License Version 1.1 but Sections 14 and 15 have been added to cover
* use of software over a computer network and provide for limited attribution
* for the Original Developer. In addition, Exhibit A has been modified to be
* consistent with Exhibit B.
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is OpenEMM.
* The Original Developer is the Initial Developer.
* The Initial Developer of the Original Code is AGNITAS AG. All portions of
* the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights
* Reserved.
*
* Contributor(s): AGNITAS AG.
********************************************************************************/
package org.agnitas.util;
import java.util.Hashtable;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Sub {
public interface CB {
public void cb_sub_setup (String id, Hashtable <String, String> param);
public void cb_sub_done (String id, Hashtable <String, String> param);
public String cb_sub_exec (String id, Hashtable <String, String> param, Object privData);
}
class Element implements CB {
Element next;
String pure;
String cbID;
String cbFull;
Hashtable <String, String>
cbParm;
CB cb;
public void cb_sub_setup (String id, Hashtable <String, String> param) {
}
public void cb_sub_done (String id, Hashtable <String, String> param) {
}
public String cb_sub_exec (String id, Hashtable <String, String> unused, Object privData) {
return pure;
}
protected Element () {
next = null;
pure = null;
cbID = null;
cbFull = null;
cbParm = null;
cb = null;
}
protected Element (String s) {
this ();
pure = s;
cb = this;
}
protected Element (String nCbID, String nCbFull) {
this ();
cbID = nCbID;
cbFull = nCbFull;
cbParm = new Hashtable <String, String> ();
}
protected void next (Element nNext) {
next = nNext;
}
protected Element next () {
return next;
}
protected void add (String vname, String value) {
cbParm.put (vname, value);
}
protected void setCB (CB nCb) {
cb = nCb;
}
protected boolean isCB (String cCbID) {
if (cbID != null)
return cbID.equals (cCbID);
return (cCbID == null) && (cb == null);
}
protected void setup () {
if (cb != null)
cb.cb_sub_setup (cbID, cbParm);
}
protected void done () {
if (cb != null)
cb.cb_sub_done (cbID, cbParm);
}
protected String get (Object passThrough) {
if (cb != null)
return cb.cb_sub_exec (cbID, cbParm, passThrough);
return pure != null ? pure : (cbFull != null ? cbFull : "");
}
}
Element elem, prev;
public Sub () {
elem = null;
prev = null;
}
private void addElement (Element e) {
if (prev != null)
prev.next (e);
else
elem = e;
prev = e;
}
/** Parses a string and search for variables as definied in
* pattern as a regular expression
* @param src the source string to parse
* @param pattern the regular expression for scanning the src
* @param idPattern regexp to extract the ID for this variable
* @param parmPattern regexp to extract optional parameter
* @param quotePattern regexp to remove quotes from paramter values
* @param flags regex compile flags
* @return True if pattern is found, False otherwise
*/
public boolean parse (String src, String pattern, String idPattern, String parmPattern, String quotePattern, int flags) {
boolean rc = false;
Pattern r = Pattern.compile (pattern, flags);
Matcher m = r.matcher (src);
Pattern rid = Pattern.compile (idPattern);
Matcher mid = null;
Pattern rparm = Pattern.compile (parmPattern);
Matcher mparm = null;
Pattern rquot = (quotePattern != null ? Pattern.compile (quotePattern) : null);
Matcher mquot = null;
int gnumber;
int slen, pos;
elem = null;
prev = null;
gnumber = m.groupCount () > 0 ? 1 : 0;
slen = src.length ();
for (pos = 0; pos < slen; ) {
if (m.find (pos)) {
int start = m.start ();
if (start > pos)
addElement (new Element (src.substring (pos, start)));
pos = m.end ();
String cbData = m.group (gnumber);
String cbID;
if (mid == null)
mid = rid.matcher (cbData);
else
mid.reset (cbData);
if (mid.find ()) {
cbID = mid.group (mid.groupCount () > 0 ? 1 : 0);
start = mid.end ();
} else {
cbID = cbData;
start = 0;
}
String cbParm;
if (start > 0)
cbParm = cbData.substring (start);
else
cbParm = cbData;
Element tmp = new Element (cbID, cbData);
if (mparm == null)
mparm = rparm.matcher (cbParm);
else
mparm.reset (cbParm);
if (mparm.groupCount () >= 2) {
int cbpos = 0;
int cblen = cbParm.length ();
while (cbpos < cblen)
if (mparm.find (cbpos)) {
String value = mparm.group (2);
if (rquot != null) {
if (mquot == null)
mquot = rquot.matcher (value);
else
mquot.reset (value);
if (mquot.find ())
value = mquot.group (mquot.groupCount () > 0 ? 1 : 0);
}
tmp.add (mparm.group (1), value);
cbpos = mparm.end ();
} else
break;
}
addElement (tmp);
rc = true;
} else {
addElement (new Element (src.substring (pos)));
pos = slen;
}
}
return rc;
}
public boolean parse (String src, String pattern, String idPattern, String parmPattern, String quotePattern) {
return parse (src, pattern, idPattern, parmPattern, quotePattern, 0);
}
/** Register a callback for each found element
* @param id the callback id
* @param cb the class to be called
*/
public void reg (String id, CB cb) {
for (Element tmp = elem; tmp != null; tmp = tmp.next ())
if (tmp.isCB (id))
tmp.setCB (cb);
}
/** Deinitialize all callbacks
*/
public void done () {
for (Element tmp = elem; tmp != null; tmp = tmp.next ())
tmp.done ();
}
/** Main routine to substitute an expression
* @param passThrough some object to pass through to the callback
* @return the newly generated string
*/
public String sub (Object passThrough) {
StringBuffer buffer = new StringBuffer (512);
for (Element tmp = elem; tmp != null; tmp = tmp.next ()) {
String stmp = tmp.get (passThrough);
if (stmp != null)
buffer.append (stmp);
}
return buffer.toString ();
}
}