001package votorola.s.gwt.scene.feed.ss; // Copyright 2011-2012, Michael Allan, Christian Weilbach. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE. 002 003import com.google.gson.stream.JsonWriter; 004import java.io.IOException; 005import java.util.*; 006import votorola.g.util.ArrayListX; 007 008import static votorola.g.util.ArrayListX.EMPTY_LIST; 009 010 011/** A serial jig for a bite. 012 */ 013public final class BiteJig implements votorola.s.gwt.scene.feed.Bite, SerialJig 014{ 015 016 // adding fields? ensure they are cleared in serialize() 017 018 019 /** Removes all persons from the specified list and caches them for reuse. 020 * 021 * @see #uncachePerson() 022 */ 023 void encachePersons( ArrayList<PersonJig> persons ) { encachePersons( persons, 0 ); } 024 025 026 private ArrayList<PersonJig> personCache = ArrayListX.emptyList(); // i.e. EMPTY_LIST 027 028 029 /** Removes all persons from the specified list and caches the persons from 030 * the start onwards for reuse. 031 * 032 * @see #uncachePerson() 033 */ 034 void encachePersons( final ArrayList<PersonJig> persons, final int start ) 035 { 036 for( int p = start, pN = persons.size(); p < pN; ++p ) 037 { 038 personCache.add( persons.get( p )); 039 } 040 persons.clear(); 041 } 042 043 044 045 /** Fetches a person jig from the cache, or creates a new jig if the cache is 046 * empty. 047 * 048 * @see #encachePersons(ArrayList) 049 */ 050 PersonJig uncachePerson() 051 { 052 if( personCache == EMPTY_LIST ) 053 { 054 personCache = new ArrayList<PersonJig>( /*initial capacity*/20 ); // lots for PersonJig's vote traces 055 } 056 057 return personCache.size() > 0? personCache.remove(0): new PersonJig(BiteJig.this); 058 } 059 060 061 062 // - B i t e -------------------------------------------------------------------------- 063 064 065 public DiffLookJig difference() { return difference; } 066 067 068 private DiffLookJig difference; 069 070 071 private void difference( final JsonWriter out ) throws IOException 072 { 073 if( difference == null ) return; 074 075 out.name( "difference" ); 076 difference.serialize( out ); 077 difference = null; 078 } 079 080 081 private DiffLookJig differenceC; 082 083 084 /** Ensures the difference is set to a jig and caches the jig for reuse. 085 * 086 * @return the jig that was set. 087 */ 088 public DiffLookJig setDifference() 089 { 090 if( differenceC == null ) differenceC = new DiffLookJig(); 091 092 difference = differenceC; 093 return differenceC; 094 } 095 096 097 098 public MessageJig message() { return messages.size() == 0? null: messages.get( 0 ); } 099 100 101 102 public List<MessageJig> messages() { return messages; } 103 104 105 private ArrayList<MessageJig> messages = ArrayListX.emptyList(); // i.e. EMPTY_LIST 106 107 108 private void messages( final JsonWriter out ) throws IOException 109 { 110 if( messages.size() == 0 ) return; // that is the default in BiteJS 111 112 out.name( "messages" ); 113 out.beginArray(); 114 for( MessageJig jig: messages ) jig.serialize( out ); 115 out.endArray(); 116 messagesC.addAll( messages ); 117 messages.clear(); 118 } 119 120 121 private ArrayList<MessageJig> messagesC = messages; 122 123 124 /** Adds a message jig, caching it for reuse. 125 * 126 * @return the jig added. 127 */ 128 public MessageJig addMessage() 129 { 130 if( messages == EMPTY_LIST ) 131 { 132 messages = new ArrayList<MessageJig>( /*initial capacity*/1 ); 133 messagesC = new ArrayList<MessageJig>( /*initial capacity*/1 ); 134 } 135 136 final MessageJig jig; 137 if( messagesC.size() > 0 ) jig = messagesC.remove( 0 ); 138 else jig = new MessageJig(); 139 140 messages.add( jig ); 141 return jig; 142 } 143 144 public char relation() { return relation; } 145 146 private char relation = ' '; 147 148 private void relation( final JsonWriter out ) throws IOException 149 { 150 if( relation == ' ' ) return; 151 152 out.name("relation").value( relation ); 153 relation = ' '; 154 } 155 156 /** Sets the relation of the first person to the other 157 * in difference related messages. 158 */ 159 public void setRelation( final char c ) { relation = c; } 160 161 162 public Date sentDate() { return sentDate; } 163 164 165 private Date sentDate = null; 166 167 168 private void sentDate( final JsonWriter out ) throws IOException 169 { 170 if( sentDate == null ) return; 171 172 out.name( "sentDate" ).value( sentDate.getTime() ); 173 sentDate = null; 174 } 175 176 177 /** Sets the date on which the bite was parsed. 178 */ 179 public void setSentDate( final Date pd ) { sentDate = pd; } // OPT a single Date instance should be cached for reuse; or better yet it should be a long 180 181 182 183 public PersonJig person() { return persons.size() == 0? null: persons.get( 0 ); } 184 185 186 187 public List<PersonJig> persons() { return persons; } 188 189 190 private ArrayList<PersonJig> persons = ArrayListX.emptyList(); // i.e. EMPTY_LIST 191 192 193 private void persons( final JsonWriter out ) throws IOException 194 { 195 if( persons.size() == 0 ) return; // that is the default in BiteJS 196 197 out.name( "persons" ); 198 out.beginArray(); 199 for( PersonJig jig: persons ) jig.serialize( out ); 200 out.endArray(); 201 encachePersons( persons ); 202 } 203 204 205 /** Adds a person jig, caching it for reuse. 206 * 207 * @return the jig added. 208 */ 209 public PersonJig addPerson() 210 { 211 if( persons == EMPTY_LIST ) persons = new ArrayList<PersonJig>( /*initial capacity*/2 ); 212 213 final PersonJig jig = uncachePerson(); 214 persons.add( jig ); 215 return jig; 216 } 217 218 219 220 public PollJig poll() { return poll; } 221 222 223 private PollJig poll; 224 225 226 private void poll( final JsonWriter out ) throws IOException 227 { 228 if( poll == null ) return; 229 230 out.name( "poll" ); 231 poll.serialize( out ); 232 poll = null; 233 } 234 235 236 private PollJig pollC; 237 238 239 /** Ensures the poll is set to a jig and caches the jig for reuse. 240 * 241 * @return the jig that was set. 242 */ 243 public PollJig setPoll() 244 { 245 if( pollC == null ) pollC = new PollJig(); 246 247 poll = pollC; 248 return pollC; 249 } 250 251 252 253 // - S e r i a l - J i g -------------------------------------------------------------- 254 255 256 public void serialize( final JsonWriter out ) throws IOException 257 { 258 out.beginObject(); 259 260 difference( out ); 261 messages( out ); 262 relation( out ); 263 sentDate( out ); 264 persons( out ); 265 poll( out ); 266 267 out.endObject(); 268 } 269 270}