001package edu.wpi.first.wpilibj.networktables2;
002
003import edu.wpi.first.wpilibj.networktables2.AbstractNetworkTableEntryStore.TableListenerManager;
004import edu.wpi.first.wpilibj.networktables2.connection.*;
005import edu.wpi.first.wpilibj.networktables2.type.*;
006import java.io.*;
007
008
009/**
010 * An entry in a network table
011 * 
012 * @author mwills
013 *
014 */
015public class NetworkTableEntry {
016        /**
017         * the id that represents that an id is unknown for an entry
018         */
019        public static final char UNKNOWN_ID = (char)0xFFFF;
020
021        private char id;
022        private char sequenceNumber;
023        /**
024         * the name of the entry
025         */
026        public final String name;
027        /**
028         * the type of the entry
029         */
030        private NetworkTableEntryType type;
031        private Object value;
032        private volatile boolean isNew = true;
033        private volatile boolean isDirty = false;
034
035        /**
036         * Create a new entry with the given name, type, value, an unknown id and a sequence number of 0
037         * @param name
038         * @param type
039         * @param value
040         */
041        public NetworkTableEntry(final String name, final NetworkTableEntryType type, final Object value){
042                this(UNKNOWN_ID, name, (char)0, type, value);
043        }
044        /**
045         * Create a new entry with the given id, name, sequence number, type and value
046         * @param id
047         * @param name
048         * @param sequenceNumber
049         * @param type
050         * @param value
051         */
052        public NetworkTableEntry(final char id, final String name, final char sequenceNumber, final NetworkTableEntryType type, final Object value){
053                this.id = id;
054                this.name = name;
055                this.sequenceNumber = sequenceNumber;
056                this.type = type;
057                this.value = value;
058        }
059
060        /**
061         * @return the id of the entry
062         */
063        public char getId() {
064                return id;
065        }
066        /**
067         * @return the current value of the entry
068         */
069        public Object getValue(){
070                return value;
071        }
072        /**
073         * @return the type of the entry
074         */
075        public NetworkTableEntryType getType(){
076                return type;
077        }
078        private static final char HALF_OF_CHAR = 32768;
079        /**
080         * set the value of the entry if the given sequence number is greater that the current sequence number
081         * @param newSequenceNumber the sequence number of the incoming entry
082         * @param newValue the new value
083         * @return true if the value was set
084         */
085        public boolean putValue(final char newSequenceNumber, final Object newValue) {
086                if( (sequenceNumber < newSequenceNumber && newSequenceNumber - sequenceNumber < HALF_OF_CHAR)
087                                || (sequenceNumber > newSequenceNumber && sequenceNumber - newSequenceNumber > HALF_OF_CHAR) ){
088                        value = newValue;
089                        sequenceNumber = newSequenceNumber;
090                        return true;
091                }
092                return false;
093        }
094        /**
095         * force a value and new sequence number upon an entry
096         * @param newSequenceNumber
097         * @param newValue
098         */
099        public void forcePut(final char newSequenceNumber, final Object newValue) {
100                value = newValue;
101                sequenceNumber = newSequenceNumber;
102        }
103        /**
104         * force a value and new sequence number upon an entry, Will also set the type of the entry
105         * @param newSequenceNumber
106         * @param type
107         * @param newValue
108         */
109        public void forcePut(final char newSequenceNumber, final NetworkTableEntryType type, final Object newValue) {
110                this.type = type;
111                forcePut(newSequenceNumber, newValue);
112        }
113        
114        
115        public void makeDirty() {
116                isDirty = true;
117        }
118        public void makeClean() {
119                isDirty = false;
120        }
121        public boolean isDirty(){
122                return isDirty;
123        }
124
125        /**
126         * Send the value of the entry over the output stream
127         * @param os
128         * @throws IOException
129         */
130        public void sendValue(final DataOutputStream os) throws IOException{
131                type.sendValue(value, os);
132        }
133
134        /**
135         * @return the current sequence number of the entry
136         */
137        public char getSequenceNumber() {
138                return sequenceNumber;
139        }
140        /**
141         * Sets the id of the entry
142         * @param id the id of the entry
143         * @throws IllegalStateException if the entry already has a known id
144         */
145        public void setId(final char id) throws IllegalStateException{
146                if(this.id!=UNKNOWN_ID)
147                        throw new IllegalStateException("Cannot set the Id of a table entry that already has a valid id");
148                this.id = id;
149        }
150        /**
151         * clear the id of the entry to unknown
152         */
153        public void clearId() {
154                id = UNKNOWN_ID;
155        }
156        
157        public void send(NetworkTableConnection connection) throws IOException {
158                connection.sendEntryAssignment(this);
159        }
160        public void fireListener(TableListenerManager listenerManager) {//TODO determine best way to handle complex data
161                listenerManager.fireTableListeners(name, value, isNew);
162                isNew = false;
163        }
164
165        public String toString(){
166                return "Network Table "+type.name+" entry: "+name+": "+(int)getId()+" - "+(int)getSequenceNumber()+" - "+getValue();
167        }
168
169        
170        
171}