public ResourceBE CreateProperty(uint?parentId, XUri parentUri, ResourceBE.ParentType parentType, string name, ResourceContentBE content, string description, string etag, AbortEnum abort) { //TODO: The parent resource isn't verified when the resource name and the parent info is given ResourceBE prop = _resourceBL.GetResource(parentId, parentType, ResourceBE.Type.PROPERTY, name, DeletionFilter.ACTIVEONLY); if (prop != null) { switch (abort) { case AbortEnum.Exists: throw new PropertyExistsConflictException(name); case AbortEnum.Modified: _resourceBL.ValidateEtag(etag, prop, true); break; } prop = _resourceBL.BuildRevForContentUpdate(prop, content.MimeType, content.Size, description, null, content); prop = _resourceBL.SaveResource(prop); DekiContext.Current.Instance.EventSink.PropertyUpdate(DekiContext.Current.Now, prop, DekiContext.Current.User, parentType, parentUri); } else { if ((abort == AbortEnum.Modified) && !string.IsNullOrEmpty(etag)) { throw new PropertyUnexpectedEtagConflictException(); } prop = _resourceBL.BuildRevForNewResource(parentId, parentType, name, content.MimeType, content.Size, description, ResourceBE.Type.PROPERTY, DekiContext.Current.User.ID, content); prop = _resourceBL.SaveResource(prop); DekiContext.Current.Instance.EventSink.PropertyCreate(DekiContext.Current.Now, prop, DekiContext.Current.User, parentType, parentUri); } return(prop); }
public virtual ResourceBE BuildRevForNewResource(uint?parentId, ResourceBE.ParentType parentType, string resourcename, MimeType mimeType, uint size, string description, ResourceBE.Type resourceType, uint userId, ResourceContentBE content) { ResourceBE newResource = BuildRevForNewResource(resourcename, mimeType, size, description, resourceType, userId, content); switch (parentType) { case ResourceBE.ParentType.PAGE: newResource.ParentPageId = parentId; break; case ResourceBE.ParentType.USER: newResource.ParentUserId = parentId; break; default: newResource.ParentId = parentId; break; } newResource.ChangeMask = newResource.ChangeMask | ResourceBE.ChangeOperations.PARENT; return(newResource); }
private void PropertyChanged(DateTime eventTime, ResourceBE prop, UserBE user, ResourceBE.ParentType parentType, XUri parentUri, params string[] path) { try { string parent = string.Empty; switch (parentType) { case ResourceBE.ParentType.PAGE: parent = PAGES; break; case ResourceBE.ParentType.FILE: parent = FILES; break; case ResourceBE.ParentType.USER: parent = USERS; break; case ResourceBE.ParentType.SITE: parent = SITE; break; } XUri channel = _channel.At(parent).At(PROPERTY).At(path); XUri resource = prop.PropertyInfoUri(parentUri); string[] origin = new string[] { resource.ToString() }; XDoc doc = new XDoc("deki-event") .Elem("channel", channel) .Elem("name", prop.Name) .Elem("uri", resource) .Start("content") .Attr("mime-type", prop.MimeType.FullType) .Attr("size", prop.Size) .Attr("href", prop.PropertyContentUri(parentUri)); if (prop.MimeType.MainType == MimeType.TEXT.MainType && prop.Size < 256) { doc.Value(ResourceContentBL.Instance.Get(prop).ToText()); } doc.End(); if (parentType == ResourceBE.ParentType.PAGE) { doc.Elem("pageid", prop.ParentPageId ?? 0); } else if (parentType == ResourceBE.ParentType.USER) { doc.Elem("userid", prop.ParentUserId ?? 0); } else if (parentType == ResourceBE.ParentType.FILE) { ResourceBE attachment = ResourceBL.Instance.GetResource(prop.ParentId.Value); doc.Elem("fileid", attachment.MetaXml.FileId ?? 0); PageDependentChanged(eventTime, PageBL.GetPageById(attachment.ParentPageId.Value), user, ArrayUtil.Concat(new string[] { FILES, PROPERTY }, path)); } Queue(eventTime, channel, resource, origin, doc); } catch (Exception e) { _log.WarnExceptionMethodCall(e, "PropertyChanged", "event couldn't be created"); } }
private void NotifyPropertyParent(DateTime eventTime, ResourceBE prop, UserBE user, ResourceBE.ParentType parentType, string action) { if (parentType == ResourceBE.ParentType.PAGE && prop.ParentPageId != null) { PageBE parentPage = PageBL.GetPageById(prop.ParentPageId.Value); if (parentPage != null) { PageDependentChanged(eventTime, parentPage, user, PROPERTY, action); } } else if (parentType == ResourceBE.ParentType.USER) { // Owner of property may not be same as requesting user. // The dependentschanged event is triggered on the property owner. if (prop.ParentUserId != null) { // Optimization to avoid a db call when operating on your own user property. if (user.ID != prop.ParentUserId.Value) { user = UserBL.GetUserById(prop.ParentUserId.Value); if (user == null) { _log.WarnFormat("Could not find owner user (id: {0}) of user property (key: {1})", prop.ParentUserId.Value, prop.Name); return; } } } UserDependentChanged(eventTime, user, PROPERTY, action); } //TODO (maxm): trigger file property changes }
public void PropertyDelete(DateTime eventTime, ResourceBE prop, UserBE user, ResourceBE.ParentType parentType, XUri parentUri) { NotifyPropertyParent(eventTime, prop, user, parentType, DELETE); PropertyChanged(eventTime, prop, user, parentType, parentUri, DELETE); }
public IList <ResourceBE> GetResources(uint?parentId, ResourceBE.ParentType parentType, IList <ResourceBE.Type> resourceTypes, string[] names, DeletionFilter deletionStateFilter) { uint[] parentids = parentId == null ? new uint[] { } : new[] { parentId.Value }; return(GetResources(parentids, parentType, resourceTypes, names, deletionStateFilter, null, null, null)); }
/// <summary> /// Returns a hash by parentid's based on parentType of lists of child resources /// </summary> /// <param name="resources"></param> /// <param name="parentType"></param> /// <returns></returns> public Dictionary <ulong, IList <ResourceBE> > GroupByParentIdWithCast(IEnumerable <ResourceBE> resources, ResourceBE.ParentType parentType) { Dictionary <ulong, List <ResourceBE> > temp = GroupByParentIdInternal(resources, parentType); Dictionary <ulong, IList <ResourceBE> > ret = new Dictionary <ulong, IList <ResourceBE> >(); //Convert lists to arrays foreach (KeyValuePair <ulong, List <ResourceBE> > kvp in temp) { ret[kvp.Key] = kvp.Value; } return(ret); }
public ResourceBE UpdatePropertyContent(ResourceBE prop, ResourceContentBE content, string changeDescription, string eTag, AbortEnum abort, XUri parentUri, ResourceBE.ParentType parentType) { if (abort == AbortEnum.Modified) { _resourceBL.ValidateEtag(eTag, prop, true); } prop = _resourceBL.BuildRevForContentUpdate(prop, content.MimeType, content.Size, changeDescription, null, content); prop = _resourceBL.SaveResource(prop); DekiContext.Current.Instance.EventSink.PropertyUpdate(DekiContext.Current.Now, prop, DekiContext.Current.User, parentType, parentUri); return(prop); }
public ResourceBE DeleteProperty(ResourceBE prop, ResourceBE.ParentType parentType, XUri parentUri) { DekiContext.Current.Instance.EventSink.PropertyDelete(DekiContext.Current.Now, prop, DekiContext.Current.User, parentType, parentUri); return(_resourceBL.Delete(prop)); }
public ResourceBE[] SaveBatchProperties(uint?parentId, XUri parentUri, ResourceBE.ParentType parentType, XDoc doc, out string[] failedNames, out Dictionary <string, Exception> saveStatusByName) { //This is a specialized method that saves a batch of property updates in one request and connects them with a transaction. //Successful updates are returned //Status/description of each property update is returned as well as a hash of dreammessages by name saveStatusByName = new Dictionary <string, Exception>(); List <string> failedNamesList = new List <string>(); Dictionary <string, ResourceBE> resourcesByName = new Dictionary <string, ResourceBE>(); List <ResourceBE> ret = new List <ResourceBE>(); //Get list of names and perform dupe check foreach (XDoc propDoc in doc["/properties/property"]) { string name = propDoc["@name"].AsText ?? string.Empty; if (resourcesByName.ContainsKey(name)) { throw new PropertyDuplicateInvalidOperationException(name); } resourcesByName[name] = null; } //Retrieve current properties with given name resourcesByName = _resourceBL.GetResources(parentId, parentType, ResourceBL.PROPERTIES, new List <string>(resourcesByName.Keys).ToArray(), DeletionFilter.ACTIVEONLY).AsHash(e => e.Name); //extract property info, build resource revisions, save resource, and maintain statuses for each save foreach (XDoc propDoc in doc["/properties/property"]) { ResourceBE res = null; string content; uint contentLength = 0; string description = string.Empty; string etag = null; MimeType mimeType; string name = string.Empty; try { name = propDoc["@name"].AsText ?? string.Empty; resourcesByName.TryGetValue(name, out res); if (propDoc["contents"].IsEmpty) { if (res == null) { throw new PropertyDeleteDoesNotExistInvalidArgumentException(name); } else { res = DeleteProperty(res, parentType, parentUri); } } else { //parse content from xml etag = propDoc["@etag"].AsText; description = propDoc["description"].AsText; content = propDoc["contents"].Contents; contentLength = (uint)(content ?? string.Empty).Length; string mimeTypeStr = propDoc["contents/@type"].AsText; if (string.IsNullOrEmpty(mimeTypeStr) || !MimeType.TryParse(mimeTypeStr, out mimeType)) { throw new PropertyMimtypeInvalidArgumentException(name, mimeTypeStr); } ResourceContentBE resourceContent = new ResourceContentBE(content, mimeType); if (res == null) { //new property res = CreateProperty(parentId, parentUri, parentType, name, resourceContent, description, etag, AbortEnum.Exists); } else { //new revision res = UpdatePropertyContent(res, resourceContent, description, etag, AbortEnum.Modified, parentUri, parentType); } } ret.Add(res); saveStatusByName[name] = null; } catch (ResourcedMindTouchException x) { //Unexpected errors fall through while business logic errors while saving a property continues processing saveStatusByName[name] = x; failedNamesList.Add(name); } catch (DreamAbortException x) { // TODO (arnec): remove this once all usage of DreamExceptions is purged from Deki logic //Unexpected errors fall through while business logic errors while saving a property continues processing saveStatusByName[name] = x; failedNamesList.Add(name); } } failedNames = failedNamesList.ToArray(); return(ret.ToArray()); }