001/* 002 * Copyright (c) 2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.ROADnet; 031 032import java.lang.reflect.Array; 033import java.lang.reflect.Field; 034 035import ptolemy.actor.lib.Transformer; 036import ptolemy.data.ObjectToken; 037import ptolemy.data.RecordToken; 038import ptolemy.data.Token; 039import ptolemy.data.type.BaseType; 040import ptolemy.kernel.CompositeEntity; 041import ptolemy.kernel.util.IllegalActionException; 042import ptolemy.kernel.util.NameDuplicationException; 043 044/** 045 * Ptolemy actor to produce from an ObjectToken a RecordToken, with record 046 * entries corresponding to fields within the object carried by the ObjectToken. 047 * This actor was originally written to eliminate the need for special 048 * field-accessor actors for each class transported with ObjectToken; it seems 049 * like a logical enough thing to do, as an Object is pretty much a record where 050 * names can map to other Objects (fields) or to function closures (methods). 051 * This actor ignores methods completely. 052 * 053 * <p> 054 * <img src="http://mercali.ucsd.edu/~tobin/OrbObjectToRecordDemo.png"/> 055 * </p> 056 * 057 * @author Tobin Fricke (tobin@splorg.org), University of California 058 * @version $Id: ObjectToRecord.java 24234 2010-05-06 05:21:26Z welker $ 059 * @see RecordToObject 060 * @Pt.ProposedRating Red (tobin) 061 */ 062 063public class ObjectToRecord extends Transformer { 064 065 /** 066 * @param container 067 * The container. 068 * @param name 069 * The name of this actor. 070 * @exception IllegalActionException 071 * If the actor cannot be contained by the proposed 072 * container. 073 * @exception NameDuplicationException 074 * If the container already has an actor with this name. 075 */ 076 077 public ObjectToRecord(CompositeEntity container, String name) 078 throws NameDuplicationException, IllegalActionException { 079 super(container, name); 080 081 input.setTypeEquals(BaseType.OBJECT); 082 // output.setTypeAtLeast(new RecordType(new String[0], new Type[0])); // 083 // FIXME 084 } 085 086 public boolean prefire() throws IllegalActionException { 087 return (input.hasToken(0) && super.prefire()); 088 } 089 090 /** 091 * Accept an ObjectToken from the input and produce a corresponding 092 * RecordToken on the output. 093 */ 094 095 public void fire() throws IllegalActionException { 096 super.fire(); 097 098 Object o = ((ObjectToken) (input.get(0))).getValue(); 099 Class c = o.getClass(); 100 Field[] fields = c.getFields(); 101 int nFields = Array.getLength(fields); 102 103 String[] labels = new String[nFields]; 104 ObjectToken[] values = new ObjectToken[nFields]; 105 106 for (int i = 0; i < nFields; i++) { 107 Field f = (Field) (Array.get(fields, i)); 108 labels[i] = f.getName(); 109 try { 110 /* 111 * Here there is room to do something smart, like convert 112 * java.lang.String objects into StringTokens. 113 */ 114 values[i] = new ObjectToken(f.get(o)); 115 } catch (IllegalAccessException e) { 116 values[i] = new ObjectToken(null); // not the best approach 117 } 118 } 119 120 /* 121 * It might be useful to either include the classname as a field in the 122 * record (problematic due to possible name collission), as a separate 123 * token, or even in a higher level of recordToken wrapping. 124 */ 125 126 Token r = new RecordToken(labels, values); 127 output.broadcast(r); 128 } 129 130}