001package votorola.a.web.gwt; // Copyright 2010-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 com.google.gwt.dom.client.*;
004import com.google.gwt.http.client.URL;
005import com.google.gwt.regexp.shared.RegExp;
006import java.util.regex.MatchResult;
007import votorola.a.*;
008import votorola.a.position.*;
009import votorola.a.voter.*;
010import votorola.g.*;
011import votorola.g.web.gwt.*;
012
013
014/** A pollwiki from the viewpoint of a GWT client.
015  *
016  *     @see App#pollwiki()
017  */
018public final class PollwikiG implements Pollwiki
019{
020
021
022    /** Does nothing itself but the call forces static initialization of this class.
023      */
024    static void forceInitClass() {}
025
026
027
028   // ------------------------------------------------------------------------------------
029
030
031    /** Encodes a page name and appends it to the wiki {@linkplain #getLocation() base
032      * URL}.  Usage example:<pre>
033      *
034      *     String href = voteServer.pollwiki().encodePageSpecifier(
035      *       "Main page" ).build().toASCIIString();</pre>
036      *
037      *     @see #appendPageSpecifier(String)
038      */
039    public StringBuilder encodePageSpecifier( String pageName )
040    {
041        // cf. MediaWiki.encodePageSpecifier
042
043        final StringBuilder b = new StringBuilder( wikiLocation );
044        pageName = MediaWiki.demiEncodedPageName( pageName, maybeUgly ); // fully encoded here:
045        if( maybeUgly )
046        {
047            b.append( "?title=" );
048            b.append( URL.encodeQueryString( pageName ));
049        }
050        else
051        {
052            b.append( '/' );
053            b.append( URLX.encodePath( pageName ));
054        }
055        return b;
056    }
057
058
059
060    /** The base URL for requesting pages from the pollwiki, without a trailing slash (/).
061      * This is either the standard access URL ending in "index.php" for example, or a
062      * pretty alias per <code>$wgUsePathInfo</code>.
063      *
064      *     @see #appendPageSpecifier(String)
065      *     @see #maybeUgly()
066      *     @see #setLocation(String)
067      */
068    public static @GWTConfigCallback String getLocation() { return wikiLocation; }
069      // cf. votorola.a.PollwikiVS.uri()
070
071
072        private static String wikiLocation;
073
074
075        private static native void exposeLocation()
076        /*-{
077            $wnd.a_web_gwt_PollwikiG_getLocation = $entry(
078              @votorola.a.web.gwt.PollwikiG::getLocation() );
079            $wnd.a_web_gwt_PollwikiG_setLocation = $entry(
080              @votorola.a.web.gwt.PollwikiG::setLocation(Ljava/lang/String;) );
081        }-*/;
082
083            static
084            {
085                assert AMod.isForcedInit(): "forced init " + PollwikiG.class.getName();
086                exposeLocation();
087            }
088
089
090        /** Sets the base URL for requesting pages from the pollwiki.  Call it from the
091          * global configuration function {@linkplain AMod voGWTConfig.a} in this
092          * manner:<pre
093          *
094         *>   a_web_gwt_PollwikiG_setLocation( 'http://<var>YOUR.DOM</var>/wiki' );
095          *     // defaults to http://SCRIPT-LOCATION/index.php</pre>
096          *
097          *     @throws IllegalArgumentException if the location ends with a slash '/'
098          *       character.
099          *     @see #getLocation()
100          *     @see #setScriptLocation(String)
101          */
102        public static @GWTConfigCallback void setLocation( final String s )
103        {
104            if( s.endsWith( "/" )) throw new IllegalArgumentException( "location ends with '/'" );
105
106            wikiLocation = s;
107            maybeUgly = MAYBE_UGLY_URL_PATTERN.exec(s) != null;
108        }
109
110
111
112    /** The base URL for script execution in the pollwiki, without a trailing slash (/).
113      * For example <code>http://reluk.ca/mediawiki</code>.  Script requests may be
114      * constructed by appending the script path and parameters:<pre
115      *
116     *>    getScriptLocation() + "/index.php?oldid=1138"</pre>
117      *
118      *     @see #setScriptLocation(String)
119      */
120    public static @GWTConfigCallback String getScriptLocation() { return wikiScriptLocation; }
121      // cf. votorola.a.PollwikiVS.wikiScriptURI()
122
123
124        private static String wikiScriptLocation;
125
126
127        private static native void exposeScriptLocation()
128        /*-{
129            $wnd.a_web_gwt_PollwikiG_getScriptLocation = $entry(
130              @votorola.a.web.gwt.PollwikiG::getScriptLocation() );
131            $wnd.a_web_gwt_PollwikiG_setScriptLocation = $entry(
132              @votorola.a.web.gwt.PollwikiG::setScriptLocation(Ljava/lang/String;) );
133        }-*/;
134
135            static
136            {
137                assert AMod.isForcedInit(): "forced init " + PollwikiG.class.getName();
138                exposeScriptLocation();
139            }
140
141
142        /** Sets base URL for for script execution in the pollwiki.  Call it from the
143          * global configuration function {@linkplain AMod voGWTConfig.a} in this
144          * manner:<pre
145          *
146         *>   a_web_gwt_PollwikiG_setScriptLocation( 'http://<var>YOUR.DOM</var>/mediawiki' );
147          *     // defaults to the standard location http://SERVER.DOM/mediawiki
148          *     // where SERVER.DOM is a calculated guess at the web server name</pre>
149          *
150          *     @throws IllegalArgumentException if the location ends with a slash '/'
151          *       character.
152          *     @see #getScriptLocation()
153          */
154        public static @GWTConfigCallback void setScriptLocation( final String s )
155        {
156            if( s.endsWith( "/" )) throw new IllegalArgumentException( "location ends with '/'" );
157
158            wikiScriptLocation = s;
159        }
160
161
162
163    /** Returns the position identifier of the loaded page, or null if the page is not a
164      * position page.
165      */
166    public PositionID identifyAsPosition( final Document page )
167    {
168        final String pageName = WindowX.js()._get( "wgPageName" );
169        if( pageName == null ) return null; // not a MediaWiki page
170
171        return identifyAsPosition( pageName );
172    }
173
174
175
176    /** Returns the position identifier of the loaded page, or null if the page is not a
177      * position page.
178      */
179    public PositionID identifyAsPosition( final String pageName )
180    {
181        final MatchResult m = MediaWiki.parsePageNameS( pageName );
182        if( m == null ) return null; // not a MediaWiki page
183
184        final String personName = IDPair.normalUsername( m.group( 2 ));
185        final String pollName;
186        if( pipeRecognizer.isPipeName( personName ))
187        {
188            pollName = datumValue( "pipePoll", Document.get() );
189              // per http://havoc.zelea.com/w/Category:Pipe
190        }
191        else pollName = m.group( 3 ); // subpage path if any
192        if( pollName == null ) return null;
193
194        return new PositionID( personName, pollName );
195    }
196
197
198
199   // - P o l l w i k i ------------------------------------------------------------------
200
201
202    /** @see #getLocation()
203      * @see #encodePageSpecifier(String)
204      */
205    public StringBuilder appendPageSpecifier( final String encodedPageName )
206    {
207        return MediaWiki.appendPageSpecifier( new StringBuilder(wikiLocation), maybeUgly,
208          encodedPageName );
209    }
210
211
212
213    /** @see #getLocation()
214      */
215    public boolean maybeUgly() { return maybeUgly; }
216
217
218        private static boolean maybeUgly;
219
220
221
222    /** @see #setPipeRecognizer(String,String)
223      */
224    public PipeRecognizer pipeRecognizer() { return pipeRecognizer; }
225
226
227        private static PipeRecognizer pipeRecognizer = new PipeRecognizer0(); // by default
228
229
230        private static native void exposePipeRecognizer()
231        /*-{
232            $wnd.a_web_gwt_PollwikiG_setPipeRecognizer = $entry(
233              @votorola.a.web.gwt.PollwikiG::setPipeRecognizer(Ljava/lang/String;Ljava/lang/String;) );
234        }-*/;
235
236            static
237            {
238                assert AMod.isForcedInit(): "forced init " + PollwikiG.class.getName();
239                exposePipeRecognizer();
240            }
241
242
243        /** Configures the pipe recognizer.  Call this method from the global
244          * configuration function {@linkplain AMod voGWTConfig.a} in this manner:<pre
245          *
246         *>   a_web_gwt_PollwikiG_setPipeRecognizer( 'PREFIX', 'SUFFIX' );
247          *     // there are no dependable defaults, you should set values if pipes are enabled</pre>
248          *
249          *     @see #pipeRecognizer()
250          *     @see <a href='http://havoc.zelea.com/w/Category:Pipe#Enabling_pipes_in_the_wiki'
251          *                              target='_top'>Category:Pipe#Enabling pipes in the wiki</a>
252          */
253        public static @GWTConfigCallback void setPipeRecognizer( final String pipePrefix,
254          final String pipeSuffix )
255        {
256            pipeRecognizer = new PipeRecognizer1( pipePrefix, pipeSuffix );
257        }
258
259
260
261    public String positionPageName( final String personName, final String pollName )
262    {
263        return PositionID.pageName( personName, pollName, pipeRecognizer() );
264    }
265
266
267
268//// P r i v a t e ///////////////////////////////////////////////////////////////////////
269
270
271    /** Returns the value of a datum encoded in the loaded pollwiki page, or null if none
272      * is encoded.
273      *
274      *     @see <a href='http://havoc.zelea.com/w/Template:Data_encoded'
275      *                              target='_top'>Template:Data encoded</a>
276      */// per INLDOC
277    private String datumValue( final String name, final Document page )
278    {
279        final Element span = page.getElementById( name );
280        return span == null? null: span.getTitle();
281    }
282
283
284
285    private static final RegExp MAYBE_UGLY_URL_PATTERN = RegExp.compile(
286      ".+/index\\.php[0-9]*.*" ); // changing?  change also in g.MediaWiki
287
288
289}