package com.planet_ink.siplet.support;
import java.util.*;
public class MXPElement implements Cloneable
{
public static final int BIT_OPEN=1;
public static final int BIT_COMMAND=2;
public static final int BIT_NEEDTEXT=4;
public static final int BIT_SPECIAL=8;
public static final int BIT_HTML=16;
public static final int BIT_NOTSUPPORTED=32;
public static final int BIT_EATTEXT=64;
public static final int BIT_DISABLED=128;
private String name="";
private String definition="";
private String attributes="";
private String flag="";
private String unsupportedParms="";
private int bitmap=0;
private Vector parsedAttributes=null;
private Hashtable attributeValues=null;
private Hashtable alternativeAttributes=null;
private Vector userParms=new Vector();
private boolean basicElement=true;
private int bufInsert=-1;
public MXPElement(String newName,
String theDefinition,
String theAttributes,
String theFlag,
int theBitmap)
{
super();
name=newName;
definition=theDefinition;
attributes=theAttributes;
flag=theFlag;
bitmap=theBitmap;
if((!isCommand())
&&(theDefinition.toUpperCase().indexOf("&TEXT;")>=0))
bitmap=bitmap|BIT_NEEDTEXT;
}
public MXPElement(String newName,
String theDefinition,
String theAttributes,
String theFlag,
int theBitmap,
String unsupported)
{
super();
name=newName;
definition=theDefinition;
attributes=theAttributes;
flag=theFlag;
bitmap=theBitmap;
if((!isCommand())
&&(theDefinition.toUpperCase().indexOf("&TEXT;")>=0))
bitmap=bitmap|BIT_NEEDTEXT;
unsupportedParms=unsupported;
}
public MXPElement copyOf()
{
try
{
MXPElement E=(MXPElement)this.clone();
if(E.parsedAttributes!=null) E.parsedAttributes=(Vector)E.parsedAttributes.clone();
if(E.attributeValues!=null) E.attributeValues=(Hashtable)E.attributeValues.clone();
if(E.alternativeAttributes!=null) E.alternativeAttributes=(Hashtable)E.alternativeAttributes.clone();
if(E.userParms!=null) E.userParms=(Vector)E.userParms.clone();
return E;
}
catch(Exception e){};
return this;
}
public String name(){return name;}
public void setName(String newName){name=newName;}
public boolean isCommand(){return Util.bset(bitmap,BIT_COMMAND);}
public boolean isOpen(){return Util.bset(bitmap,BIT_OPEN);}
public boolean isHTML(){return Util.bset(bitmap,BIT_HTML);}
public boolean isSpecialProcessor(){return Util.bset(bitmap,BIT_SPECIAL);}
public boolean isDisabled(){return Util.bset(bitmap,BIT_DISABLED);}
public boolean isTextEater(){return Util.bset(bitmap,BIT_EATTEXT);}
public String getDefinition(){return definition;}
public void setDefinition(String defi){definition=defi;}
public String getAttributes(){return attributes;}
public boolean needsText(){return Util.bset(bitmap,BIT_NEEDTEXT);}
public void setNotBasicElement(){basicElement=false;}
public boolean isBasicElement(){return basicElement;}
public boolean isGenerallySupported(){return !Util.bset(bitmap,BIT_NOTSUPPORTED);}
public void setBitmap(int newBitmap){bitmap=newBitmap;}
public int getBitmap(){return bitmap;}
public Vector getUnsupportedParms()
{
if((unsupportedParms==null)||(unsupportedParms.trim().length()==0))
return new Vector();
return Util.parseSpaces(unsupportedParms,true);
}
public void setAttributes(String newAttributes)
{
attributes=newAttributes;
parsedAttributes=null;
attributeValues=null;
alternativeAttributes=null;
}
public String getAttributeValue(String tag)
{
getParsedAttributes();
return (String)attributeValues.get(tag.toUpperCase().trim());
}
public void setAttributeValue(String tag, String value)
{
getParsedAttributes();
attributeValues.remove(tag);
if(value!=null)
attributeValues.put(tag,value);
}
public synchronized Vector getParsedAttributes()
{
if(parsedAttributes!=null) return parsedAttributes;
parsedAttributes=new Vector();
attributeValues=new Hashtable();
alternativeAttributes=new Hashtable();
StringBuffer buf=new StringBuffer(attributes.trim());
StringBuffer bit=new StringBuffer("");
char quotes='\0';
int i=-1;
char lastC=' ';
boolean firstEqual=false;
while((bit!=null)&&((++i)<buf.length()))
{
switch(buf.charAt(i))
{
case '=':
if((!firstEqual)&&(bit.length()>0))
{
String tag=bit.toString().toUpperCase().trim();
bit=new StringBuffer("");
parsedAttributes.addElement(tag);
attributeValues.put(tag,bit);
}
else
bit.append(buf.charAt(i));
firstEqual=true;
break;
case '\n':
case '\r':
case ' ':
case '\t':
if(quotes=='\0')
{
if((!firstEqual)&&(bit.length()>0))
parsedAttributes.addElement(bit.toString().toUpperCase().trim());
bit=new StringBuffer("");
firstEqual=false;
}
else
bit.append(buf.charAt(i));
break;
case '"':
case '\'':
if(lastC=='\\')
bit.append(buf.charAt(i));
else
if((lastC=='=')
||(quotes!='\0')
||((quotes=='\0')&&((lastC==' ')||(lastC=='\t'))))
{
if((quotes!='\0')&&(quotes==buf.charAt(i)))
{
quotes='\0';
if((!firstEqual)&&(bit.length()>0))
parsedAttributes.addElement(bit.toString().toUpperCase().trim());
bit=new StringBuffer("");
firstEqual=false;
}
else
{
if(quotes!='\0')
bit.append(buf.charAt(i));
else
quotes=buf.charAt(i);
}
}
else
bit.append(buf.charAt(i));
break;
default:
bit.append(buf.charAt(i));
break;
}
lastC=buf.charAt(i);
}
if((!firstEqual)&&(bit.length()>0))
parsedAttributes.addElement(bit.toString().toUpperCase().trim());
for(int p=parsedAttributes.size()-1;p>=0;p--)
{
String PA=(String)parsedAttributes.elementAt(p);
StringBuffer VAL=(StringBuffer)attributeValues.get(PA);
if((VAL!=null)&&(parsedAttributes.contains(VAL.toString())))
{
parsedAttributes.removeElementAt(p);
attributeValues.remove(PA);
alternativeAttributes.put(PA,VAL.toString());
}
}
return parsedAttributes;
}
public String getFlag(){return flag;}
public Vector getUserParms(){return userParms;}
public void saveSettings(int insertPoint, Vector theUserParms)
{
bufInsert=insertPoint;
userParms=theUserParms;
}
public int getBufInsert(){return bufInsert;}
public void deleteAttribute(String name)
{
getParsedAttributes();
attributeValues.remove(name.toUpperCase().trim());
}
public Vector getCloseTags(String desc)
{
StringBuffer buf=new StringBuffer(desc);
Vector tags=new Vector();
StringBuffer bit=null;
char quotes='\0';
int i=-1;
char lastC=' ';
while((++i)<buf.length())
{
switch(buf.charAt(i))
{
case '<':
if(quotes!='\0')
bit=null;
else
if(bit!=null)
{
if(MXP.tagDebug){System.out.println("/TAG/CLOSER2S="+Util.toStringList(tags)); System.out.flush();}
return tags;
}
else
bit=new StringBuffer("");
break;
case '>':
if((quotes=='\0')&&(bit!=null)&&(bit.toString().trim().length()>0))
tags.add(bit.toString().toUpperCase().trim());
bit=null;
break;
case ' ':
case '\t':
if((quotes=='\0')&&(bit!=null)&&(bit.toString().trim().length()>0))
tags.add(bit.toString().toUpperCase().trim());
bit=null;
break;
case '"':
case '\'':
if(lastC=='\\')
bit=null;
else
if((quotes!='\0')
&&(quotes==buf.charAt(i)))
quotes='\0';
else
if(quotes=='\0')
quotes=buf.charAt(i);
bit=null;
break;
default:
if((bit!=null)&&(Character.isLetterOrDigit(buf.charAt(i))))
bit.append(buf.charAt(i));
else
bit=null;
break;
}
lastC=buf.charAt(i);
}
if(MXP.tagDebug){System.out.println("/TAG/CLOSERS="+Util.toStringList(tags)); System.out.flush();}
return tags;
}
public String getFoldedDefinition(String text)
{
Vector aV=getParsedAttributes();
attributeValues.remove("TEXT");
attributeValues.put("TEXT",text);
if((userParms!=null)&&(userParms.size()>0))
{
int position=-1;
String avParm=null;
String userParm=null;
for(int u=0;u<userParms.size();u++)
{
userParm=((String)userParms.elementAt(u)).toUpperCase().trim();
int xx=userParm.indexOf("=");
if((xx>0)&&(alternativeAttributes.containsKey(userParm.substring(0,xx).trim())))
{
String newKey=(String)alternativeAttributes.get(userParm.substring(0,xx).trim());
String uu=(String)userParms.elementAt(u);
xx=uu.indexOf("=");
userParms.setElementAt(newKey+uu.substring(xx),u);
userParm=((String)userParms.elementAt(u)).toUpperCase().trim();
}
boolean found=false;
for(int a=0;a<aV.size();a++)
{
avParm=(String)aV.elementAt(a);
if((userParm.startsWith(avParm+"="))||(avParm.equals(userParm)))
{
found=true;
if(a>position) position=a;
attributeValues.remove(avParm);
String val=(avParm.equals(userParm))?"":((String)userParms.elementAt(u)).trim().substring(avParm.length()+1);
attributeValues.put(avParm,val);
break;
}
}
if((!found)&&(position<(aV.size()-1)))
{
position++;
avParm=(String)aV.elementAt(position);
attributeValues.remove(avParm);
attributeValues.put(avParm,((String)userParms.elementAt(u)).trim());
}
}
}
return definition;
}
}