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}