001package votorola.a.position; // Copyright 2013, 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 java.net.*;
005import java.util.regex.*;
006import javax.mail.internet.*;
007import votorola.a.*;
008import votorola.a.voter.*;
009import votorola.g.*;
010import votorola.g.lang.*;
011
012
013/** An identifier of a position, including a paired identifier for the person.  This is
014  * factored out as a subclass in order to preserve GWT compatibility in the base class.
015  */
016public @ThreadSafe final class PositionIDPair extends PositionID
017{
018
019
020    private PositionIDPair( final IDPair person, String _pollName )
021    {
022        super( person.username(), _pollName );
023        this.person = person;
024    }
025
026
027
028    /** Constructs a PositionIDPair.
029      *
030      *     @param pageName the name of the position page.  It will automatically be
031      *       normalized if necessary.
032      *     @param content0 the wikitext of the position page including at least section 0.
033      *     @param rev the revision identifier of the content.
034      */
035    static PositionIDPair newID( final PollwikiVS wiki, final String pageName, final int rev,
036      final String content0 ) throws MalformedPageName, PipeRevision.MalformedContent
037    {
038        final MatchResult mR = MediaWiki.parsePageNameS( pageName );
039        if( mR == null ) throw new IllegalArgumentException( "malformed page name:" + pageName );
040
041        final String username = mR.group( 2 );
042        final String subpageName =  mR.group( 3 );
043        final String pollName;
044        if( subpageName == null )
045        {
046            if( !wiki.pipeRecognizer().isPipeName( username ))
047            {
048                throw new MalformedPageName(
049                  "page is not a pipe and should therefore be a subpage, but is not: " + pageName,
050                  wiki.scriptURI(), rev );
051            }
052
053            final Matcher m = PipeRevision.TEMPLATE_CALL_PATTERN.matcher( content0 );
054            if( !m.find() )
055            {
056                throw new PipeRevision.MalformedContent( "missing or malformed pipe template call",
057                  wiki.scriptURI(), rev );
058            }
059
060            pollName = m.group( 1 );
061        }
062        else pollName = subpageName;
063        final IDPair person;
064        try{ person = IDPair.fromUsername( username ); }
065        catch( final AddressException x )
066        {
067            throw new MalformedPageName( "username is not mailish: " + username, x, wiki.scriptURI(),
068              rev );
069        }
070
071        return new PositionIDPair( person, pollName );
072    }
073
074
075
076   // ------------------------------------------------------------------------------------
077
078
079    /** The identifier of the person.
080      */
081    public IDPair person() { return person; }
082
083
084        private final IDPair person;
085
086
087
088   // ====================================================================================
089
090
091    /** Thrown when a request cannot be met because a page name is not in the form
092      * required for a position page.
093      */
094    static final @ThreadSafe class MalformedPageName extends IOException implements UserInformative
095    {
096
097        /** @param wikiScriptURI the base URL for script execution in the wiki, without a
098          *   trailing slash (/).
099          */
100        MalformedPageName( final String message, Throwable _cause, final URI wikiScriptURI,
101          final int rev )
102        {
103            super( message + " | " + MediaWiki.revLoc(wikiScriptURI,rev), _cause );
104        }
105
106
107        /** @param wikiScriptURI the base URL for script execution in the wiki, without a
108          *   trailing slash (/).
109          */
110        MalformedPageName( final String message, final URI wikiScriptURI, final int rev )
111        {
112            super( message + " | " + MediaWiki.revLoc(wikiScriptURI,rev) );
113        }
114
115    }
116
117
118}