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}