package votorola.a.voter; // Copyright 2008-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. import javax.mail.internet.*; import org.apache.wicket.*; import org.apache.wicket.request.mapper.parameter.PageParameters; import votorola.a.web.wic.*; import votorola.g.*; import votorola.g.lang.*; import votorola.g.mail.*; import votorola.g.web.wic.*; import static votorola.a.voter.IDPair.NOBODY; /** A page that is navigable by user. The particular user to display is specified by * query parameter 'u' or 'v'. All instances of VoterPage support the following query * parameters: * * * * * * * * * * * * * * * * * * * * * *
KeyValueDefault
uThe {@linkplain IDPair#username() username} of the voter. Any {@linkplain * MediaWiki#demiEncodedPageName(String,boolean) demi-encoding} with underscores * in place of spaces is automatically decoded. Incompatible with parameter 'v'; * specify one or the other.Null, specifying no particular user.
vThe {@linkplain IDPair#email() email address} of the user. Incompatible * with parameter 'u'; specify one or the other.Null, specifying no particular user.
*/ public interface VoterPage { // - V o t e r - P a g e -------------------------------------------------------------- /** Identifies the voter by canonical email address. * * @see #voterIDPair() */ public String voterEmail(); /** Identifies either the voter who is viewed on this page, or {@linkplain * IDPair#NOBODY nobody}. * * @see #voterEmail() * @see #voterUsername() */ public IDPair voterIDPair(); /** The voter's username as derived from the email address. * * @see #voterIDPair() */ public String voterUsername(); // ==================================================================================== /** Session scope for instances of VoterPage. * * @see VSession#scopeVoterPage() */ public static @ThreadSafe final class SessionScope implements java.io.Serializable { private static final long serialVersionUID = 0L; /** Constructs a SessionScope. */ public SessionScope( VSession session ) { this.session = session; } private final VSession session; // -------------------------------------------------------------------------------- /** Identifies either the last voter fore-navigated to, or {@linkplain * IDPair#NOBODY nobody}. * * @see #setLastIDPair(IDPair) */ public IDPair getLastIDPair() { return lastIDPair; } private volatile IDPair lastIDPair = NOBODY; /** Sets the identity of the last voter fore-navigated to. Setting it to * {@linkplain IDPair#NOBODY NOBODY} will clear it to default. * * @see #getLastIDPair() */ public void setLastIDPair( final IDPair newLastIDPair ) { if( newLastIDPair.equals( lastIDPair )) return; // or throw NullPointerException lastIDPair = newLastIDPair; if( !setLastIDPair_done && !NOBODY.equalsEmail( newLastIDPair )) { setLastIDPair_done = true; } session.dirty(); // per Session API } private volatile boolean setLastIDPair_done; /** The ID pair of either the last voter fore-navigated to, or the authenticated user, * or {@linkplain IDPair#NOBODY NOBODY}. The return value defaults to the user * only if no voter has ever been navigated to. Once a voter has been navigated * to, this method will default directly to NOBODY. */ public IDPair getLastVoterOrUser() { IDPair idPair = lastIDPair; // snapshot copy, for atomic test/return if( !setLastIDPair_done && NOBODY.equalsEmail( idPair )) { idPair = session.userOrNobody(); } return idPair; } // /** The ID pair of either the currently displayed voter; or the last // * fore-navigated to. If the current page is a voter page, and is displaying a // * voter, then the voter is returned. Otherwise, the value of // * getLastVoterOrUserEmail() is returned. The values differ only if the user has // * back-navigated to the current page, which would not be reflected in // * getLastVoterOrUserEmail(). // */ // public IDPair lastVoterDisplayed( final VRequestCycle cycle ) // { // final Page page = cycle.responsePage(); // IDPair idPair = NOBODY; // if( page instanceof VoterPage ) idPair = ((VoterPage)page).voterIDPair(); // // if( NOBODY.equalsEmail( idPair )) idPair = getLastVoterOrUser(); // // return idPair; // } // No clients anymore, and VRequestCycle.responsePage() needs work as of 1.5. } // ==================================================================================== /** Voter page utilities. */ public static @ThreadRestricted("wicket") final class U { private U() {} /** Extracts the ID pair corresponding to query parameter 'u' or 'v' if either is * specified; otherwise returns {@linkplain IDPair#NOBODY}. * * @throws RestartResponseException redirecting to an error message page if * both 'u' and 'v' are specified, or either is malformed. */ public static IDPair idPairOrNobodyFor( final PageParameters p ) { final IDPair idPair; final String username = p.get( "u" ).toString(); final String email = p.get( "v" ).toString(); try { if( username == null ) { if( email == null ) idPair = IDPair.NOBODY; else idPair = IDPair.fromEmail( InternetAddressX.canonicalAddress( email )); } else { if( email != null ) { VSession.get().error( "both parameters 'u' and 'v' specified" ); throw new RestartResponseException( new WP_Message() ); } idPair = IDPair.fromUsername( MediaWiki.demiDecodedPageName( username )); /// not actually necessary, has no effect on result [not true] // idPair = IDPair.fromUsername( username ); } } catch( AddressException x ) { VSession.get().error( x.toString() ); throw new RestartResponseException( new WP_Message() ); } return idPair; } /** Sets the appropriate identifier parameter ('u' or 'v') as specified by the ID * pair, and clears the other parameter; or clears both if ID pair is {@linkplain * IDPair#NOBODY NOBODY}. If p is null, and a value needs to be set, then p is * automatically constructed and returned. * * @param p the parameters, which may be null. * @return the same page parameters. */ @SuppressWarnings("deprecation") public static PageParameters setFrom( final IDPair idPair, PageParameters p ) { if( IDPair.NOBODY.equalsEmail( idPair )) { if( p != null ) { p.remove( "u" ); p.remove( "v" ); } } else if( idPair.isFromEmail() ) { if( p != null ) p.remove( "u" ); p = PageParametersX.withSet( p, "v", idPair.email() ); } else { if( p != null ) p.remove( "v" ); p = PageParametersX.withSet( p, "u", idPair.username() ); } return p; } /** Returns the specified page parameters (pP) with a value for the identifier * parameter ('u' or 'v') as recalled from the session. If a value is recalled * but pP is null, then pP is automatically constructed. * * @param pP the parameter map, which may be null. */ public static PageParameters withRecall_u_v( final PageParameters pP ) { return setFrom( VSession.get().scopeVoterPage().getLastIDPair(), pP ); } } }