001package votorola.a.trust; // Copyright 2010, 2012, Michael Allan. 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 java.io.*; 004import votorola.a.*; 005import votorola.g.io.*; 006import votorola.g.lang.*; 007 008 009/** A completed trace of a neigbourhood trust network, which also serves as a residential 010 * voter register and (till we start aggregating multiple registers) a simple voter list. 011 * To query for a registrant's membership in electoral districts and other 012 * divisions:</p><pre 013 * 014 *> Set<String> divisionSet = trace.membershipTable().divisionSet( 015 * registrant.email() );</pre> 016 * 017 * <p>Other registration properties are lumped together in a single trace node, one per 018 * registrant. To obtain the registrant's trace node:</p><pre 019 * 020 *> TraceNode traceNode = trace.traceNodeTable().getOrCreate( registrant );</pre> 021 * 022 * <p>Most of the registration properties are set by intermediation of the local 023 * administrator's <code>votrace.js</code> script.</p> 024 * 025 * @see <a href='http://reluk.ca/project/votorola/s/_/example/full/home/vdev/votorola/trust/votrace.js' 026 * >Working example of <code>votrace.js</code></a> 027 */ 028public @ThreadSafe final class NetworkTrace implements Serializable 029{ 030 031 // cf. a/count/Count. NetworkTrace is currently superflous, as we have no meta-data to 032 // model. 033 034 035 private static final long serialVersionUID = 2L; 036 // depends not only on structure of this class, but also structure of relational tables 037 038 039 040 /** Partially constructs a NetworkTrace. 041 * 042 * @see #init(Membership.Table,TraceNodeW.Table) 043 */ 044 NetworkTrace( ReadyDirectory _readyDirectory ) { readyDirectory = _readyDirectory; } 045 046 047 048 /** Completes the construction of a new VoterList. 049 */ 050 @ThreadRestricted("constructor") 051 void init( Membership.Table _membershipTable, TraceNodeW.Table _traceNodeTable ) 052 { 053 membershipTable = _membershipTable; 054 traceNodeTable = _traceNodeTable; 055 } 056 057 058 059 // ```````````````````````````````````````````````````````````````````````````````````` 060 061 062 /** Returns true if this trace is probably in sync with the serial file of the 063 * specified ready directory; false if that file has since been modified or deleted. 064 * Always returns false if the trace was never originally deserialized from that 065 * file path. 066 * 067 * @see #readObjectFromSerialFile(ReadyDirectory) 068 */ 069 boolean isObjectReadFromSerialFile( final ReadyDirectory newReadyDirectory ) 070 { 071 if( readObjectFromSerialFile_modTime == 0L 072 || !readyDirectory.equals( newReadyDirectory )) return false; 073 074 final File serialFile = readyDirectory.newTraceSerialFile(); 075 return readObjectFromSerialFile_modTime == serialFile.lastModified(); // 0L if file does not exist 076 } 077 078 079 080 public static NetworkTrace readObjectFromSerialFile( final ReadyDirectory readyDirectory ) 081 { 082 final File serialFile = readyDirectory.newTraceSerialFile(); 083 final NetworkTrace t = new NetworkTrace( readyDirectory ); 084 t.readObjectFromSerialFile_modTime = serialFile.lastModified(); 085 return t; 086 } 087 088 089 private long readObjectFromSerialFile_modTime; // final after readObjectFromSerialFile 090 091 092 093 final void writeObjectToSerialFile() throws IOException 094 { 095 final File serialFile = readyDirectory.newTraceSerialFile(); 096 FileX.ensuredirs( serialFile.getParentFile() ); 097 FileX.writeObject( NetworkTrace.this, serialFile ); 098 } 099 100 101 102 // ------------------------------------------------------------------------------------ 103 104 105 /** The relational store of memberships that (in part) backs this trace, if known. It 106 * is a table named "{@linkplain Membership.Table#SCHEMA_NAME 107 * SCHEMA_NAME}.<var>YYYY-MD-S</var>-membership-<var>S</var>", stored in the output 108 * database. 109 * 110 * @return reference to relational store; or null, if the trace was not 111 * initialized with a reference 112 * 113 * @see votorola.a.VoteServer.Run#database() 114 * @see #init(Membership.Table,TraceNodeW.Table) 115 */ 116 public Membership.Table membershipTable() { return membershipTable; } 117 118 119 private transient Membership.Table membershipTable; // final after init 120 121 122 123 /** The relational store of trace nodes that (in part) backs this trace, if known. It 124 * is a table named "{@linkplain TraceNodeW.Table#SCHEMA_NAME 125 * SCHEMA_NAME}.<var>YYYY-MD-S</var>-trace_node-<var>S</var>", stored in the output 126 * database. 127 * 128 * @return reference to relational store; or null, if the trace was not 129 * initialized with a reference 130 * 131 * @see votorola.a.VoteServer.Run#database() 132 * @see #init(Membership.Table,TraceNodeW.Table) 133 */ 134 public TraceNodeW.Table traceNodeTable() { return traceNodeTable; } 135 136 137 private transient TraceNodeW.Table traceNodeTable; // final after init 138 139 140 141 /** The file part of the backing for this trace. 142 */ 143 public ReadyDirectory readyDirectory() { return readyDirectory; } 144 145 146 private transient ReadyDirectory readyDirectory; // final after init 147 148 149 150 // ==================================================================================== 151 152 153 /** API for all traces of trust networks within the scope of a vote-server. 154 * 155 * @see VoteServer#scopeTrace() 156 */ 157 public static @ThreadSafe final class VoteServerScope 158 { 159 160 /** Constructs a VoteServerScope. 161 */ 162 public @Warning( "non-API" ) VoteServerScope( final VoteServer vS ) 163 { 164 final String loc = "votrace" + File.separator; 165 readyToReportLink = new File( vS.outDirectory(), loc + "_readyTrace_report" ); 166 snapToReportLink = new File( vS.outDirectory(), loc + "_snap_report" ); 167 } 168 169 170 // -------------------------------------------------------------------------------- 171 172 173 /** The path of the <code>_readyTrace_report</code> symbolic link. When this link 174 * exists, it points to the ready directory of the currently reported trace. 175 * 176 * @return abstract path (never null) of symbolic link. 177 * 178 * @see <a href='../../../../../s/manual.xht#line-votrace'>votrace</a> 179 */ 180 public File readyToReportLink() { return readyToReportLink; } 181 182 183 private final File readyToReportLink; 184 185 186 /** The path of the <code>_snap_report</code> symbolic link. When this link 187 * exists, it points to the snap directory of the currently reported trace. This 188 * is for informational and external use only, all code should instead use 189 * {@linkplain #readyToReportLink() readyToReportLink}. 190 * 191 * @return abstract path (never null) of symbolic link. 192 */ 193 public File snapToReportLink() { return snapToReportLink; } 194 195 196 private final File snapToReportLink; 197 198 } 199 200 201}