📄 referencemanager.java
字号:
refBy.remove(pageName); m_referredBy.remove( referredPageName ); m_referredBy.put( referredPageName, refBy ); log.debug("After cleaning m_referredBy HashMap key:value "+referredPageName+":"+m_referredBy.get( referredPageName )); } log.debug("Removing from m_refersTo HashMap key:value "+pageName+":"+m_refersTo.get( pageName )); m_refersTo.remove( pageName ); } /** * Updates the referred pages of a new or edited WikiPage. If a refersTo * entry for this page already exists, it is removed and a new one is built * from scratch. Also calls updateReferredBy() for each referenced page. * <P> * This is the method to call when a new page has been created and we * want to a) set up its references and b) notify the referred pages * of the references. Use this method during run-time. * * @param page Name of the page to update. * @param references A Collection of Strings, each one pointing to a page this page references. */ public synchronized void updateReferences( String page, Collection references ) { // // Create a new entry in m_refersTo. // Collection oldRefTo = (Collection)m_refersTo.get( page ); m_refersTo.remove( page ); m_refersTo.put( page, references ); // // We know the page exists, since it's making references somewhere. // If an entry for it didn't exist previously in m_referredBy, make // sure one is added now. // if( !m_referredBy.containsKey( page ) ) { m_referredBy.put( page, new TreeSet() ); } // // Get all pages that used to be referred to by 'page' and // remove that reference. (We don't want to try to figure out // which particular references were removed...) // cleanReferredBy( page, oldRefTo, references ); // // Notify all referred pages of their referinesshoodicity. // Iterator it = references.iterator(); while( it.hasNext() ) { String referredPageName = (String)it.next(); updateReferredBy( referredPageName, page ); } } /** * Returns the refers-to list. For debugging. */ protected Map getRefersTo() { return( m_refersTo ); } /** * Returns the referred-by list. For debugging. */ protected Map getReferredBy() { return( m_referredBy ); } /** * Cleans the 'referred by' list, removing references by 'referrer' to * any other page. Called after 'referrer' is removed. */ private void cleanReferredBy( String referrer, Collection oldReferred, Collection newReferred ) { // Two ways to go about this. One is to look up all pages previously // referred by referrer and remove referrer from their lists, and let // the update put them back in (except possibly removed ones). // The other is to get the old referred to list, compare to the new, // and tell the ones missing in the latter to remove referrer from // their list. Hm. We'll just try the first for now. Need to come // back and optimize this a bit. if( oldReferred == null ) return; Iterator it = oldReferred.iterator(); while( it.hasNext() ) { String referredPage = (String)it.next(); Set oldRefBy = (Set)m_referredBy.get( referredPage ); if( oldRefBy != null ) { oldRefBy.remove( referrer ); } // If the page is referred to by no one AND it doesn't even // exist, we might just as well forget about this entry. // It will be added again elsewhere if new references appear. if( ( ( oldRefBy == null ) || ( oldRefBy.isEmpty() ) ) && ( m_engine.pageExists( referredPage ) == false ) ) { m_referredBy.remove( referredPage ); } } } /** * When initially building a ReferenceManager from scratch, call this method * BEFORE calling updateReferences() with a full list of existing page names. * It builds the refersTo and referredBy key lists, thus enabling * updateReferences() to function correctly. * <P> * This method should NEVER be called after initialization. It clears all mappings * from the reference tables. * * @param pages a Collection containing WikiPage objects. */ private synchronized void buildKeyLists( Collection pages ) { m_refersTo.clear(); m_referredBy.clear(); if( pages == null ) return; Iterator it = pages.iterator(); try { while( it.hasNext() ) { WikiPage page = (WikiPage)it.next(); // We add a non-null entry to referredBy to indicate the referred page exists m_referredBy.put( page.getName(), new TreeSet() ); // Just add a key to refersTo; the keys need to be in sync with referredBy. m_refersTo.put( page.getName(), null ); } } catch( ClassCastException e ) { log.fatal( "Invalid collection entry in ReferenceManager.buildKeyLists().", e ); } } /** * Marks the page as referred to by the referrer. If the page does not * exist previously, nothing is done. (This means that some page, somewhere, * has a link to a page that does not exist.) * <P> * This method is NOT synchronized. It should only be referred to from * within a synchronized method, or it should be made synced if necessary. */ private void updateReferredBy( String page, String referrer ) { // We're not really interested in first level self-references. if( page.equals( referrer ) ) { return; } // Neither are we interested if plural forms refer to each other. if( m_matchEnglishPlurals ) { String p2 = page.endsWith("s") ? page.substring(0,page.length()-1) : page+"s"; if( referrer.equals(p2) ) { return; } } Set referrers = (Set)m_referredBy.get( page ); // Even if 'page' has not been created yet, it can still be referenced. // This requires we don't use m_referredBy keys when looking up missing // pages, of course. if(referrers == null) { referrers = new TreeSet(); m_referredBy.put( page, referrers ); } referrers.add( referrer ); } /** * Clears the references to a certain page so it's no longer in the map. * * @param pagename Name of the page to clear references for. */ public synchronized void clearPageEntries( String pagename ) { m_referredBy.remove(pagename); } /** * Finds all unreferenced pages. This requires a linear scan through * m_referredBy to locate keys with null or empty values. */ public synchronized Collection findUnreferenced() { ArrayList unref = new ArrayList(); Set keys = m_referredBy.keySet(); Iterator it = keys.iterator(); while( it.hasNext() ) { String key = (String) it.next(); //Set refs = (Set) m_referredBy.get( key ); Set refs = getReferenceList( m_referredBy, key ); if( refs == null || refs.isEmpty() ) { unref.add( key ); } } return unref; } /** * Finds all references to non-existant pages. This requires a linear * scan through m_refersTo values; each value must have a corresponding * key entry in the reference Maps, otherwise such a page has never * been created. * <P> * Returns a Collection containing Strings of unreferenced page names. * Each non-existant page name is shown only once - we don't return information * on who referred to it. */ public synchronized Collection findUncreated() { TreeSet uncreated = new TreeSet(); // Go through m_refersTo values and check that m_refersTo has the corresponding keys. // We want to reread the code to make sure our HashMaps are in sync... Collection allReferences = m_refersTo.values(); Iterator it = allReferences.iterator(); while( it.hasNext() ) { Collection refs = (Collection)it.next(); if( refs != null ) { Iterator rit = refs.iterator(); while( rit.hasNext() ) { String aReference = (String)rit.next(); if( m_engine.pageExists( aReference ) == false ) { uncreated.add( aReference ); } } } } return uncreated; } /** * Searches for the given page in the given Map. */ private Set getReferenceList( Map coll, String pagename ) { Set refs = (Set)coll.get( pagename ); if( m_matchEnglishPlurals ) { // // We'll add also matches from the "other" page. // Set refs2; if( pagename.endsWith("s") ) { refs2 = (Set)coll.get( pagename.substring(0,pagename.length()-1) ); } else { refs2 = (Set)coll.get( pagename+"s" ); } if( refs2 != null ) { if( refs != null ) refs.addAll( refs2 ); else refs = refs2; } } return refs; } /** * Find all pages that refer to this page. Returns null if the page * does not exist or is not referenced at all, otherwise returns a * collection containing page names (String) that refer to this one. * <p> * @param pagename The page to find referrers for. * @return A Collection of Strings. (This is, in fact, a Set, and is likely * to change at some point to a Set). May return null, if the page * does not exist, or if it has no references. */ // FIXME: Return a Set instead of a Collection. public synchronized Collection findReferrers( String pagename ) { Set refs = getReferenceList( m_referredBy, pagename ); if( refs == null || refs.isEmpty() ) { return null; } else { return refs; } } /** * Returns all pages that refer to this page. Note that this method * returns an unmodifiable Map, which may be abruptly changed. So any * access to any iterator may result in a ConcurrentModificationException. * <p> * The advantages of using this method over findReferrers() is that * it is very fast, as it does not create a new object. The disadvantages * are that it does not do any mapping between plural names, and you * may end up getting a ConcurrentModificationException. * * @param pageName Page name to query. * @return A Set of Strings containing the names of all the pages that refer * to this page. May return null, if the page does not exist or * has not been indexed yet. * @since 2.2.33 */ public Set findReferredBy( String pageName ) { return (Set)m_unmutableReferredBy.get( pageName ); } /** * Returns all pages that this page refers to. You can use this as a quick * way of getting the links from a page, but note that it does not link any * InterWiki, image, or external links. It does contain attachments, though. * <p> * The Collection returned is unmutable, so you cannot change it. It does reflect * the current status and thus is a live object. So, if you are using any * kind of an iterator on it, be prepared for ConcurrentModificationExceptions. * <p> * The returned value is a Collection, because a page may refer to another page * multiple times. * * @param pageName Page name to query * @return A Collection of Strings containing the names of the pages that this page * refers to. May return null, if the page does not exist or has not * been indexed yet. * @since 2.2.33 */ public Collection findRefersTo( String pageName ) { return (Collection)m_unmutableRefersTo.get( pageName ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -