/** * *************************************************************** * JADE - Java Agent DEvelopment Framework is a framework to develop * multi-agent systems in compliance with the FIPA specifications. * Copyright (C) 2000 CSELT S.p.A. * * GNU Lesser General Public License * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * ************************************************************** */ package jade.content.frame; import java.util.Vector; import java.util.Enumeration; import java.util.Date; import java.io.*; import jade.core.AID; import jade.core.CaseInsensitiveString; import jade.content.lang.sl.SL0Vocabulary; import jade.content.lang.sl.SimpleSLTokenizer; import jade.util.leap.Iterator; import jade.lang.acl.ISO8601; /** @author Giovanni Caire - TILAB @version $Date: 2010-04-08 15:54:18 +0200 (gio, 08 apr 2010) $ $Revision: 6298 $ */ public class SLFrameCodec implements jade.util.leap.Serializable { public static final String NAME = "FIPA-SL"; /** Transform a Frame into a String encoded according to the SL language @param content The Frame to be transformed @throws FrameException */ public String encode(Frame content) throws FrameException { if (content == null) { return null; } try { StringBuffer sb = new StringBuffer(); write(sb, content); return sb.toString(); } catch (FrameException fe) { throw fe; } catch (Throwable t) { throw new FrameException("Error encoding content", t); } } /** Transform a String encoded according to the SL language into a Frame @param content The String to be transformed. @throws FrameException */ public Frame decode(String content) throws FrameException { if (content == null || content.length() == 0) { return null; } try { return (Frame) read(new SimpleSLTokenizer(content)); } catch (FrameException fe) { throw fe; } catch (Throwable t) { throw new FrameException("Error decoding content", t); } } /** */ private void write(StringBuffer sb, Object obj) throws Throwable { if (obj instanceof AID) { obj = aidToFrame((AID) obj); } if (obj instanceof QualifiedFrame) { writeQualified(sb, (QualifiedFrame) obj); } else if (obj instanceof OrderedFrame) { writeOrdered(sb, (OrderedFrame) obj); } else if (obj instanceof Date) { sb.append(ISO8601.toString((Date) obj)); } else if (obj instanceof Integer || obj instanceof Long || obj instanceof Boolean) { sb.append(obj); } //#MIDP_EXCLUDE_BEGIN else if (obj instanceof Double) { sb.append(obj); } //#MIDP_EXCLUDE_END else if (obj instanceof byte[]) { byte[] b = (byte[]) obj; sb.append('#'); sb.append(b.length); sb.append('"'); // FIXME: Should we use Base64 encoding? sb.append(new String(b)); sb.append('"'); } else if (obj instanceof String) { String s = (String)obj; if (CaseInsensitiveString.equalsIgnoreCase("true",s) || CaseInsensitiveString.equalsIgnoreCase("false",s)) { s = '"'+s+'"'; // quote it to avoid confusion with the boolean primitives } else if (!SimpleSLTokenizer.isAWord(s)) { s = SimpleSLTokenizer.quoteString(s); } sb.append(s); } else { throw new FrameException("Can't encode "+obj+" of class "+obj.getClass().getName()); } } private void writeQualified(StringBuffer sb, QualifiedFrame qf) throws Throwable { sb.append('('); sb.append(qf.getTypeName()); Enumeration e = qf.keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); sb.append(" :"); sb.append(key); sb.append(' '); write(sb, qf.get(key)); } sb.append(')'); } private void writeOrdered(StringBuffer sb, OrderedFrame of) throws Throwable { sb.append('('); sb.append(of.getTypeName()); Enumeration e = of.elements(); while (e.hasMoreElements()) { sb.append(' '); write(sb, e.nextElement()); } sb.append(')'); } /** */ private Object read(SimpleSLTokenizer st) throws Throwable { if (st.nextToken().equals("(")) { st.consumeChar('('); String typeName = st.getElement(); if (st.nextToken().startsWith(":")) { QualifiedFrame qf = new QualifiedFrame(typeName); fillQualified(st, qf); // If this QualifiedFrame represents an AID, convert it if (qf.getTypeName().equals(SL0Vocabulary.AID)) { return frameToAid(qf); } else { return qf; } } else { OrderedFrame of = new OrderedFrame(typeName); fillOrdered(st, of); return of; } } else { String val = st.getElement(); // Long try { return new Long(Long.parseLong(val)); } catch (Exception e) { } //#MIDP_EXCLUDE_BEGIN // Float try { // Note that Double.parseDouble() does not exist in PJava return Double.valueOf(val); } catch (Exception e) { } //#MIDP_EXCLUDE_END // Date try { return ISO8601.toDate(val); } catch (Exception e) { } // Boolean if (val.equals("true")) { return new Boolean(true); } if (val.equals("false")) { return new Boolean(false); } // String return val; } } private void fillQualified(SimpleSLTokenizer st, QualifiedFrame qf) throws Throwable { while (!st.nextToken().equals(")")) { String key = st.getElement(); Object val = read(st); qf.put(key, val); } st.consumeChar(')'); } private void fillOrdered(SimpleSLTokenizer st, OrderedFrame of) throws Throwable { while (!st.nextToken().equals(")")) { of.addElement(read(st)); } st.consumeChar(')'); } private final QualifiedFrame aidToFrame(AID id) { QualifiedFrame f = new QualifiedFrame(SL0Vocabulary.AID); // Name f.put(SL0Vocabulary.AID_NAME, id.getName()); // Addresses Iterator i = id.getAllAddresses(); if (i.hasNext()) { OrderedFrame addresses = new OrderedFrame(SL0Vocabulary.SEQUENCE); while (i.hasNext()) { addresses.addElement(i.next()); } f.put(SL0Vocabulary.AID_ADDRESSES, addresses); } // Resolvers i = id.getAllResolvers(); if (i.hasNext()) { OrderedFrame resolvers = new OrderedFrame(SL0Vocabulary.SEQUENCE); while (i.hasNext()) { AID res = (AID) i.next(); resolvers.addElement(aidToFrame(res)); } f.put(SL0Vocabulary.AID_RESOLVERS, resolvers); } return f; } private final AID frameToAid(QualifiedFrame f) { // Name AID id = new AID((String) f.get(SL0Vocabulary.AID_NAME), AID.ISGUID); // Addresses OrderedFrame addresses = (OrderedFrame) f.get(SL0Vocabulary.AID_ADDRESSES); if (addresses != null) { for (int i = 0; i < addresses.size(); ++i) { id.addAddresses((String) addresses.elementAt(i)); } } // Resolvers OrderedFrame resolvers = (OrderedFrame) f.get(SL0Vocabulary.AID_RESOLVERS); if (resolvers != null) { for (int i = 0; i < resolvers.size(); ++i) { AID res = frameToAid((QualifiedFrame) resolvers.elementAt(i)); id.addResolvers(res); } } return id; } }