001    /*
002     * Copyright 1999,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.feedparser;
018    
019    import java.util.HashSet;
020    
021    import org.apache.commons.feedparser.impl.DebugFeedParserListener;
022    import org.apache.commons.feedparser.locate.AnchorParser;
023    import org.apache.commons.feedparser.locate.AnchorParserException;
024    import org.apache.commons.feedparser.locate.AnchorParserListener;
025    
026    /**
027     *
028     * Experimental class to play with supporting XFN.  HTML parsing in general is
029     * interesting because I could start with the AnchorParser and move to an HTML
030     * parser but that might be too generic.
031     * 
032     * @author <a href="mailto:burton@apache.org">Kevin A. Burton (burtonator)</a>
033     * @version $Id: HTMLFeedParser.java 373614 2006-01-30 22:31:21Z mvdb $
034     */
035    public class HTMLFeedParser extends BaseParser {
036    
037        public static final HashSet XFN_RELATIONS = new HashSet();
038        
039        public static void parse( String content, final FeedParserListener listener ) throws Exception {
040    
041            if ( listener instanceof FeedDirectoryParserListener == false )
042                return;
043    
044            //FIXME: only convert to using XFN if these types of links are detected.
045            //If its just a plain XHTML file then we shouldn't use this interface.
046            //Also FeedVersion needs to be called.
047            
048            final FeedDirectoryParserListener directoryParserLisener =
049                (FeedDirectoryParserListener)listener;
050    
051            directoryParserLisener.init();
052            
053            final FeedParserState state = new FeedParserState();
054            
055            AnchorParserListener alistener = new AnchorParserListener() {
056    
057                    public void setContext( Object context ) {}
058    
059                    public Object getResult() { return null; }
060    
061                    public boolean onAnchor( String href, String rel, String title )
062                        throws AnchorParserException {
063    
064                        try {
065                            
066                            if ( rel == null || "".equals( rel ) )
067                                return true;
068    
069                            //right now these aren't valid here
070                            String description = null;
071                            String feed = null;
072                        
073                            //FIXME: only include onItem when we have at least ONE XFN
074                            //relations that valid.
075    
076                            directoryParserLisener.onItem( state, title, href, description, feed );
077                        
078                            String[] rels = rel.split( " " );
079    
080                            for ( int i = 0; i < rels.length; ++i ) {
081    
082                                String current = rels[i];
083    
084                                //FIXME: when this current rel is NOT part of any XFN
085                                //spec we should not be using the feed parser listener
086                                //because it might just be a nofollow link or such.
087    
088                                boolean isXFriendRel = XFN_RELATIONS.contains( current );
089    
090                                if ( isXFriendRel ) {
091                            
092                                    directoryParserLisener.onRelation( state,
093                                                                       current );
094                                
095                                    directoryParserLisener.onRelationEnd();
096    
097                                }
098                            
099                            }
100    
101                            directoryParserLisener.onItemEnd();
102                        
103                            //split this into individual rels... then call them.
104                        
105                            return true;
106    
107                        } catch ( Exception e ) {
108                            throw new AnchorParserException( e );
109                        }
110    
111                    }
112    
113                };
114    
115            AnchorParser.parse( content, alistener );
116    
117            directoryParserLisener.finished();
118    
119        }
120    
121        public static void main( String[] args ) throws Exception {
122    
123            FeedParserListener listener = new DebugFeedParserListener();
124            
125            parse( "<a href='http://jane-blog.example.org/' rel='sweetheart date met'>Jane</a> ",
126                   listener );
127            
128        }
129    
130        static {
131    
132            XFN_RELATIONS.add( "contact" );
133            XFN_RELATIONS.add( "acquaintance" );
134            XFN_RELATIONS.add( "friend" );
135            XFN_RELATIONS.add( "met" );
136            XFN_RELATIONS.add( "co-worker" );
137            XFN_RELATIONS.add( "colleague" );
138            XFN_RELATIONS.add( "co-resident" );
139            XFN_RELATIONS.add( "neighbor" );
140            XFN_RELATIONS.add( "child" );
141            XFN_RELATIONS.add( "parent" );
142            XFN_RELATIONS.add( "sibling" );
143            XFN_RELATIONS.add( "spouse" );
144            XFN_RELATIONS.add( "kin" );
145            XFN_RELATIONS.add( "muse" );
146            XFN_RELATIONS.add( "crush" );
147            XFN_RELATIONS.add( "date" );
148            XFN_RELATIONS.add( "sweetheart" );
149            XFN_RELATIONS.add( "me" );
150            
151        }
152        
153    }
154