///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using JetBrains.Omea.Base;
using JetBrains.Omea.Containers;
using JetBrains.Omea.OpenAPI;
namespace JetBrains.Omea.Nntp
{
///
/// Describes a node of news resource tree
///
internal class NewsTreeNode
{
public NewsTreeNode( IResource node )
{
_node = node;
}
public IResource Resource
{
get { return _node; }
}
public string DisplayName
{
get { return Resource.DisplayName; }
set { Resource.DisplayName = value; }
}
///
/// This property is shared by resources of different types with different semantics:
/// - for NewsServer, it means display name of user as it's set in the From: field of outgoing msgs
/// - for NewsGroup, it means user defined display name of a newsgroup
///
///
public string UserDisplayName
{
get
{
return Resource.GetPropText(
NntpPlugin._propUserDisplayName ).Replace( " (unsubscribed)", string.Empty );
}
set
{
if( value != null && value.Length > 0 )
{
Resource.SetProp( NntpPlugin._propUserDisplayName, value );
}
else
{
Resource.DeleteProp( NntpPlugin._propUserDisplayName );
}
}
}
public IResource Parent
{
get
{
return _node.GetLinkProp( Core.Props.Parent );
}
set
{
_node.SetProp( Core.Props.Parent, value );
}
}
public IResourceList Children
{
get
{
return _node.GetLinksTo( null, Core.Props.Parent );
}
}
public IResourceList AllSubNodes
{
get
{
IResourceList children = Children;
IResourceList result = children;
foreach( IResource child in children )
{
result = result.Union( new NewsTreeNode( child ).AllSubNodes );
}
return result;
}
}
///
/// All the groups in the tree under the tree node
///
public IResourceList Groups
{
get
{
IntArrayList groupIds = new IntArrayList();
GetGroupIds( Resource, groupIds );
return Core.ResourceStore.ListFromIds( groupIds, false );
}
}
private void GetGroupIds( IResource rootNode, IntArrayList groupIds )
{
foreach( IResource child in new NewsTreeNode( rootNode ).Children.ValidResources )
{
if( child.Type == NntpPlugin._newsGroup )
{
groupIds.Add( child.Id );
}
else
{
GetGroupIds( child, groupIds );
}
}
}
private IResource _node;
}
///
/// Describes behaviour and controls actions with news folders
///
internal class NewsFolders
{
/**
* IResource article can be null, in that case the new article is created
*/
public static IResource PlaceArticle( IResource article, IResource folder, IResourceList groups,
string from, string subject, string text, string charset, string references,
string nntpText, IResourceList attachments )
{
IResourceStore store = Core.ResourceStore;
if( !store.IsOwnerThread() )
{
IAsyncProcessor resourceProcessor = Core.ResourceAP;
article = (IResource) resourceProcessor.RunUniqueJob(
new PlaceArticleDelegate( PlaceArticle ), article, folder, groups, from,
subject, text, charset, references, nntpText, attachments );
}
else
{
if( article == null || article.IsDeleted )
{
article = store.BeginNewResource( NntpPlugin._newsLocalArticle );
}
else
{
article.BeginUpdate();
article.DeleteProp( NntpPlugin._propArticleId );
}
try
{
article.SetProp( Core.Props.Subject, subject );
article.SetProp( Core.Props.Date, DateTime.Now );
IContact sender;
NewsArticleParser.ParseFrom( article, from, out sender );
NewsArticleParser.ParseReferences( article, references );
article.SetProp( Core.Props.LongBody, text );
article.SetProp( Core.FileResourceManager.PropCharset, charset );
article.SetProp( NntpPlugin._propNntpText, nntpText );
if( !folder.IsDeleted )
{
article.SetProp( NntpPlugin._propTo, folder );
}
if( groups != null )
{
foreach( IResource group in groups )
{
if( !group.IsDeleted )
{
article.AddLink( NntpPlugin._propTo, group );
}
}
}
if( attachments != null )
{
foreach( IResource attachment in attachments )
{
if( !attachment.IsDeleted )
{
attachment.AddLink( NntpPlugin._propAttachment, article );
string actualResourceType =
Core.FileResourceManager.GetResourceTypeByExtension(
IOTools.GetExtension( attachment.GetPropText( Core.Props.Name ) ) );
if( actualResourceType != null && attachment.Type != actualResourceType )
{
attachment.ChangeType( actualResourceType );
}
if( attachment.IsTransient )
{
attachment.EndUpdate();
}
}
}
}
Core.WorkspaceManager.AddToActiveWorkspace( article );
}
finally
{
article.EndUpdate();
Core.TextIndexManager.QueryIndexing( article.Id );
}
}
return article;
}
public static void PlaceResourceToFolder( IResource res, IResource folder )
{
IResourceStore store = Core.ResourceStore;
if( !store.IsOwnerThread() )
{
Core.ResourceAP.QueueJob( JobPriority.Immediate,
new PlaceResourceToFolderDelegate( PlaceResourceToFolder ), res, folder );
}
else
{
if( !res.IsDeleted )
{
IResourceList folders = res.GetLinksFrom( NntpPlugin._newsFolder, NntpPlugin._propTo );
foreach( IResource oldfolder in folders )
{
res.DeleteLink( NntpPlugin._propTo, oldfolder );
}
res.AddLink( NntpPlugin._propTo, folder );
if( folder == SentItems )
{
res.DeleteProp( NntpPlugin._propNntpText );
}
}
}
}
public static bool IsInFolder( IResource res, IResource folder )
{
return res.HasLink( NntpPlugin._propTo, folder );
}
public static IResource Drafts
{
get
{
if( _drafts != null && !_drafts.IsDeleted )
{
return _drafts;
}
return ( _drafts = GetNewsFolderResource( Root, "Drafts", true ) );
}
}
public static IResource Outbox
{
get
{
if( _outbox != null && !_outbox.IsDeleted )
{
return _outbox;
}
return ( _outbox = GetNewsFolderResource( Root, "Outbox", true ) );
}
}
public static IResource SentItems
{
get
{
if( _sentItems != null && !_sentItems.IsDeleted )
{
return _sentItems;
}
return ( _sentItems = GetNewsFolderResource( Root, "Sent Items", true ) );
}
}
///
/// Return true if a given resource represents one of three standard news folders:
/// "Drafts", "Outbox" or "Sent Items"
///
public static bool IsDefaultFolder( IResource folder )
{
return IsDrafts( folder ) || IsOutbox( folder ) || IsSentItems( folder );
}
public static bool IsDrafts( IResource folder )
{
if( _drafts == null )
{
_drafts = GetNewsFolderResource( Root, "Drafts", false );
}
return folder == _drafts;
}
public static bool IsOutbox( IResource folder )
{
if( _outbox == null )
{
_outbox = GetNewsFolderResource( Root, "Outbox", false );
}
return folder == _outbox;
}
public static bool IsSentItems( IResource folder )
{
if( _sentItems == null )
{
_sentItems = GetNewsFolderResource( Root, "Sent Items", false );
}
return folder == _sentItems;
}
public static IResource Root
{
get
{
if( _newsgroupsRoot == null )
{
_newsgroupsRoot = Core.ResourceTreeManager.GetRootForType( NntpPlugin._newsGroup );
}
return _newsgroupsRoot;
}
}
public static void AddToRoot( IResource child )
{
new NewsTreeNode( child ).Parent = Root;
}
public static IResource GetNewsFolderResource( IResource parent, string name, bool create )
{
IResourceStore store = Core.ResourceStore;
IResourceList folders = new NewsTreeNode( parent ).Children;
folders = folders.Intersect(
store.FindResources( NntpPlugin._newsFolder, Core.Props.Name, name ), true );
IResource folder = null;
if( folders.Count > 0 )
{
folder = folders[ 0 ];
}
else
{
if( create )
{
if( !store.IsOwnerThread() )
{
folder = (IResource) Core.ResourceAP.RunUniqueJob(
new GetNewsFolderResourceDelegate( GetNewsFolderResource ), parent, name, true );
}
else
{
folder = store.BeginNewResource( NntpPlugin._newsFolder );
try
{
folder.SetProp( Core.Props.Name, name );
new NewsTreeNode( folder ).Parent = parent;
if ( parent == _newsgroupsRoot )
{
folder.SetProp( "VisibleInAllWorkspaces", true );
folder.SetProp( NntpPlugin._propNewsSortOrder, Int32.MaxValue );
}
folder.SetProp( Core.Props.DisplayThreaded, parent.GetProp( Core.Props.DisplayThreaded ) );
}
finally
{
folder.EndUpdate();
}
}
}
}
return folder;
}
private delegate IResource PlaceArticleDelegate(
IResource article, IResource folder, IResourceList groups, string from, string subject,
string text, string charset, string references, string nntpText, IResourceList attachments );
private delegate void PlaceResourceToFolderDelegate( IResource resource, IResource folder );
private delegate IResource GetNewsFolderResourceDelegate( IResource parent, string name, bool create );
private static IResource _newsgroupsRoot = null;
private static IResource _drafts = null;
private static IResource _outbox = null;
private static IResource _sentItems = null;
}
}