第四章--DMS对象介绍1


4.1、项目

当我们打开一个ProjectWise中的数据源时,在该数据源节点下会出现很多子节点,其中一个子节点叫做文档,英文为Documents,它就是我们这里所说的文档子节点。在文档子节点下,有很多文件夹子节点,这些文件夹也叫做项目,文件夹子节点下还可以继续存储子文件夹或者文档,依次嵌套。在这一部分,我将给大家介绍如何通过API操作这里我们所说的文件夹。

4.1.1、项目概念介绍

首先,很有必要给大家介绍一个ProjectWise中项目的基本知识。

正如我们上面所说的一样,项目子节点下可以继续嵌套子项目,当然也可以包含文档。一个项目在ProjectWise中存在一个唯一的标识符,在开发中我们称之为PROJ_PROP_ID,它还会存在一个父文件夹的标识符,当然这个标识符也是唯一的,在开发中我们称之为PROJ_PROP_PARENTID。项目节点这是靠这两个标识符来维持它在文档目录下的具体位置。

我们提到,一个项目包含一个PROJ_PROP_ID和PROJ_PROP_PARENTID属性,如果PROJ_PROP_PARENTID属性为0,则表示当前项目处于文档目录下的顶层。也就是当我们在ProjectWise Explorer中打开一个数据源后,初次展开Documents节点后,出现的Documents节点的直接子节点,这些子节点所包含的PROJ_PROP_PARENTID属性就是为0,知道这个特点,对我们以后操作项目会很有帮助。

在这里给大家区分一个很容易让人糊涂的概念:项目和文件夹,从使用的角度讲,它们是不同的,但是从开发的角度讲,这两个概念是一样的,都统称为Project,操作方式也基本一样。Project中有一个属性PROJ_PROP_TYPE,这个属性值如果为AADMS_PROJECT_TYPE_NORMAL就表示该Project是一个普通的文件夹,如果为AADMS_PROJECT_TYPE_RICH就表示为一个项目。

关于项目,它存在很多属性。比如说,属性PORJ_PROP_NAME表示项目的名字是什么,属性PROJ_PROP_DESC表示项目的描述是什么。通过使用界面,选中某个项目,右键选择属性,这里面关于项目的所有属性在开发中都有相对应的值来表示。详细信息可看SDK帮助文档:

4.1.2、项目函数介绍

开发中关于项目的函数很多,总的来说可以分为两大类,一类是项目操作函数,另一类是项目属性获取函数。操作类函数主要是增删查改一个项目,项目属性获取函数是指动态或静态获取指定项目的相关属性信息。

新建项目

                函数:BOOL aaApi_CreateProject2(LPAADMSPROJITEM lpProject, LONG lAccFromProject)

                介绍:这个函数在系统中创建一个新的项目

                参数:[in,out] lpPorject 是一个指向定义了所有关于项目属性的结构的指针。这个结构内的名称、存储空间和类型成员在传入是必须指定的。函数调用结束,返回时,这个结构内的其他成员将赋值为新创建的项目属性。

                           [in] lAccFromProject 指定一个项目的标识符,表示我们将把该项目的访问权限拷贝给新创建的项目。如果这个成员是0,那么父项目的访问控制权限将拷贝给该新创建的项目,如果这个成员是-1,那么新创建的项目将不会设置访问权限

                返回值:[FALSE] 创建指定的项目失败。

                              [TRUE] 项目创建成功

通过id删除项目

                函数:BOOL aaApi_DeleteProjectById(LONG lPorjectId)

                介绍:这个函数通过指定的标识符删除一个项目。如果这个项目包含文档或者子项目,或者当前用户没有权限进行删除操作,这个函数调用会失败。

                参数:[in] lProjectld 指定项目的唯一标识符

                返回值:[FALSE] 删除指定项目失败

                              [TRUE] 指定项目被成功删除

修改项目

                函数:BOOL aaApi_ModifyProjct2(LPAADMSPROJITEM lpProject)

                介绍:这个函数修改指定项目的属性

                参数:[in] lpProject 是一个指向包含需要修改的项目属性信息的结构的指针,成员lProjectld必须指定。

                返回值:[FALSE] 修改项目属性失败

                              [TURE] 项目属性修改成功

拷贝项目

                函数:BOOL aaApi_CopyProject(LONG lSourcePorjectld, LONG lTargetProjectld, ULONG ulFlags, AAPROC_PROJECTCOPY fpCallBack, AAPARAM aaUserParam, LPLOG lplCount)

                介绍:这个函数将指定的项目拷贝到其他项目下或者顶层目录。

                参数:[in] lSourceProjectld 指向源项目的标识符。如果标志AAPRO_ARRAY_ALLOW_COPY_ALL没有在ulFlags中设置,那么这个参数必选指定一个已经存在的项目。否则,这个参数也可以是0,表示拷贝当前数据源下的所有项目。

                           [in] lTargetPorjectld 指定新项目的唯一的父标识符,如果这个参数是-1,则项目将被拷贝为顶层文件夹。

                           [in] ulFlags 指定拷贝操作的选项,如果这个参数是0,那么,指定的项目和它下面的所有文件夹、文件集、文件都将递归的被拷贝,但是文档属性不会被拷贝。这个参数可是一些Project Copy Flags值的组合。

                           [in] fpCallBack 指向一个操作过程可被调用的回调函数

                           [in] aaUserParam 传入回调函数中的参数,如果fpCallBack参数是NULL,那么这个参数可以忽略。

                           [in] lplCount 是一个指向长整形的指针,该长整型保存了拷贝的项目个数。即使函数失败,被拷贝的项目标识符也会被返回(并不懂SDK中这句话什么意思)。如果AAPRO_ARRAY_NO_RECURSION没有在ulFlags中设置,那么,即使函数失败,返回的数据量也会大于0,这是因为,可能一些项目已经被成功复制了,不过在所有项目被复制之前,这个操作由于出错而被取消或终止了。

4.2、文档

4.2.1、文档概念介绍

通过上面的介绍,我们知道,一个项目下不仅可以继续嵌套子项目,还可以存放文档(Document),这一部分,我将给大家介绍关于PW上的文档的基本知识。

项目通过一个唯一的标识符来标识数据源下的一个唯一项目,而文档也存在一个标识符DOC_PROP_ID来标识当前项目下的一个唯一文档。我们需要注意的是,这个文档标识符在当前数据源下不一定是唯一的,但是在当前直接父项目下是唯一的。所以,我们确定数据源下一个唯一的一个文档,需要指定它的父标识符和其标识符。

关于文档,它存在很多属性,比如说,属性DOC_PROP_NAME表示该文档的名字是什么,属性DOC_PROP_DESC表示该文档的描述是什么,属性DOC_PROP_ID表示该文档的标识符是什么,属性DOC_PROP_PROJECTID表示该文档的父项目标识符是什么,正如我们上面所说的,这两个文件属性用来唯一确定数据源中的一个文档。通过操作界面,选中某个文档,右键选择属性,这里面关于文档的所有属性在开发中都有相对应的值来表示。详细信息可看SDK帮助文档:

3.1.2、文档函数介绍

创建文档

                函数:BOOL aaApi_CreateDocument2(LPAADOCCREATE_PARAM lpParam)

                介绍:这个函数在指定项目下创建一个新的文档。

                参数:[in] lpParam 是一个指向包含新文档标识信息的AADOCCREATE_PARAM结构体的指针。

                返回值:[FALSE] 在系统中创建指定的文档失败。

                              [TRUE] 文档创建成功

修改文档

                函数:这个函数修改已存在文档的属性

                介绍:BOOL aaApi_ModifyDocument2(LPAADOC_PARAM pParam)

                参数:[in] pParam 是一个指向包含文档新属性的AADOC_PARAM结构的指针。

                返回值:[FALSE] 修改文档的指定属性失败

                               [TRUE] 文档的指定属性修改成功

为抽象文档添加文件

                函数:BOOL aaApi_AddDocumentFile(LONG lProjectld, LONG lDocumentld, LPCWSTR lpctstrFileName)

                介绍:这个函数为指定的抽象文档添加文件。抽象文档:没有文档与之关联的文档

                参数:[in] lProjectld 指向一个文档的项目标识符

                           [in] lDocumentld 指向一个要关联文件的文档描述符

                           [in] lpctstrFileName 指向将要关联到文档的文件的路径和名字,这个参数不能为NULL

                返回值:[FALSE] 文件和文档关联失败

                              [TRUE] 文件和文档关联成功

 

删除文档的关联文件

                函数:BOOL aaApi_DeleteDocumentFile(LONG lProjectld, LONG lDocumentld)

                介绍:这个函数删除与文件关联的文档,当删除了文档的文件后,这个文档变为了抽象文档,它的文件大小变为了0

                参数:[in] lProjectld 指定文档项目的id

                           [in] lDocumentld执行文档的id

                返回值:[FALSE] 删除文档的文件成功

                              [TRUE] 文档的文件被删除成功

修改文档的关联文件

                函数:BOOL aaApi_ChangeDocumentFile(LONG lProjectld, LONG lDocumentld, LPCWSTR lpctstrFileName)

                介绍:这个函数修改文档的文件

                参数:[in] lProjectld 指向文档的项目标识符

                           [in] lDocument 指向文档标识符

                           [in] lpctstrFileName 指向一个将要和文档关联的文件的路径和名字,这个参数不能为NULL。

                返回值:[FALSE] 将文件和文档关联失败

                               [TRUE] 指定的文件和文档关联成功。

设置文档的工作流状态

                函数:BOOL aaApi_SetDocumentState(ULONG ulFlags, LONG lProjectld, LONG lDocumentld, LONG lWorkflowld, LONG lStateld, LPCWSTR lpctstrComment)

                介绍:这个函数将文档设置为工作流中的指定状态

                参数:[in] ulFlags 指定文档状态改变标志位

                           [in] lProjectld 指向文档的项目标识符

                           [in] lDocumentld 指向文档的标识符

                           [in] lWorkflowld 指定工作流标识符,

                           [in] lStateld 指定状态标识符,如果这个参数是-1,这个文档将被移动到上一个状态,如果这个参数是0,这个文档将被移动到下一个状态。

                           [in] lpctstrComment 操作注释

设置文档状态为工作流的下一状态

                函数:BOOL aaApi_ChangeDocumentToNextState(LONG lProjectNo, LONG lDocumentld, LONG lWorkflowld)

                介绍:这个函数指定文档的状态为当前关联工作流中的下一个状态

                参数:[in] lProjectNo 指定文档的项目描述符

                           [in] lDocumentld 指定文档的描述符

                           [in] lWorkflowld 指定文档的工作流描述符

                返回值:[FALSE]更改文档的状态为下一状态失败

                              [TRUE] 更改成功

设置文档状态为工作流的上一状态

                函数:BOOL aaApi_ChangeDocumentToPrevState(LONG lProjectNo, LONG lDocumentld, LONG lWorkflowld)

                介绍:这个函数指定文档的状态为当前关联工作流中的上一个状态

                参数:[in] lProjectNo 指定文档的项目描述符

                           [in] lDocumentld 指定文档的描述符

                           [in] lWorkflowld 指定文档的工作流描述符

                返回值:[FALSE]更改文档的状态为上一状态失败

                              [TRUE] 更改成功

清理文档上的工作流

                函数:BOOL aaApi_ClearDocumentWorkflow(LONG lPorjectNo, LONG lDocumentld, LONG lUserld, LPCWSTR lpctstrConmment)

                介绍:这个函数清理指定文档的工作流

                参数:[in] lProjectNo

                           [in] lDocumentld

                           [in] lUserld

                           [in] lpctstrComment

                返回值:[FALSE] 清理文档上的工作流程失败

                               [TRUE] 文档上的工作流清理成功

4.3、自定义文件夹

4.3.1、自定义文件夹概念介绍

ProjectWise中除了最基本的文档目录树,还有个人工作台目录树。个人工作台还有一种叫法是自定义文件夹,在这里我们可以根据个人喜好或需求,创建新的目录层次结构,并将文档目录树中的文件夹或文档引用到新创建的目录层次结构中,便于个人管理和查看。所以个人工作台的出发点是“人”,即每个用户都可以拥有自己的个人工作台供自己使用,并且所有用户还可以拥有一个公共的工作台供所有人使用。

 关于个人工作台,有两个概念大家必须分清楚,一个在官方SDK中叫做Custom Hierarchies,另一个叫做Custom Hierarchies Member。下面我们详细说一下这两个概念。

Custom Hierarchies(自定义层次结构)是指我们在个人工作台中新创建的、便于自己管理的新的目录层次结构,在这些层次结构下我们可将文档目录树中的文件夹或者文档引用过来。

Hierarchies Member 是引用的文档目录树中的文件夹或者文档。

4.3.2、部分函数介绍

获取自定义文件夹的顶层目录

                函数:LONG aaApi_SelectTopLevelCustomHierarchies(LONG lUserld)

                介绍:这个函数将指定用户的自定义文件中的顶层目录属性信息获取到静态缓冲区中

                参数:[in] lUserld 指定要获取哪个用户的自定义文件夹的顶层目录属性信息,指定0获取公共的自定义文件夹的属性

                返回值:0 获取失败,指定的目录没有找到

                              -1 获取失败,可查看引起该错误的错误码

                              Otherwise 获取到的自定义文件夹的顶层目录的个数。

获取自定义文件夹的某个子目录

                函数:LONG aaApi_SelectSubCustomHierarchies(LONG lParentld, LONG lUserld)

                介绍:这个函数将指定用户的自定义文件中的某个目录的子目录的属性信息获取到静态缓冲区中

                参数:[in] lParentld 指定要获取的子目录的父目录id,这个参数是必须的,必须大于0.

                           [in] lUserld 指定要获取哪个用户的自定义文件夹中目录的属性信息,指定0获取公共的自定义文件夹的目录属性

                返回值:0 获取失败,指定的目录没有找到

                              -1 获取失败,可查看引起该错误的错误码

                              Otherwise 获取到的自定义文件夹中目录的个数。

新建一个自定义层次结构

                函数:BOOL aaApi_CreteCustomHierarchy(LPLONG lplCustHrchyld, LONG lUserld, LONG lParentld, ULONG ulFlags, LPCWSTR lpctstrName, LPCWSTR lpctstrDesc)

                介绍:这个函数为指定用户新建一个具有指定属性的自定义层次结构。

                参数:[out] lplCustHrchyld 新创建成功的自定义层次结构的id

                           [in] lUsrld 指定为哪个用户创建自定义层次结构,指定0 创建一个公共的自定义层次结构,指定-1为当前用户创建一个层次结构。

                           [in] lParentld 指定新建的自定义层次结构的父自定义层次结构的id,如果指定0那么就创建顶层的自定义层次结构。

                           [in] ulFlags 指定参数掩码,这个值根据版本决定,具体看相关SDK中的介绍

                           [in] lpctstrName 指定新建的自定义层次结构的名字

                           [in] lpctstrDesc 指定新建的自定义层次结构的描述

                返回值:FALSE 新建失败

                              TRUE 新建成功

删除一个自定义层次结构

                函数:BOOL aaApi_DeleteCustomHierarchy(LONG lUserld, LONG litemld)

                介绍:删除指定的自定义层次结构和它的所有子结构

                参数:[in] lUserld 指定要删除哪个用户的自定义层次结构,指定0删除公共工作台的自定义层次结构,指定-1删除当前用户的自定义层次结构。

                           [in] litemld 指定要删除的自定义层次结构的id,如果这个值是-1,那么这个用户的所有自定义层次结构都将被删除。

                返回值:FALSE 删除失败

                              TRUE 删除成功

 

获取自定义层次结构成员的属性

                函数:LONG aaApi_SelectCustomHierarchyMembers(LONG lUserld, LONG litemld, LONG litemTYpe, LONG lMemberld, LONG lmemberld2)

                介绍:这个函数获取匹配指定规则的自定义层次结构成员的属性到静态缓冲区

                参数:[in] lUserld 将要获取的成员属性所属的自定义层次结构的用户id。指定0表示成员属于公共自定义层次结构,指定-1表示获取所有的用户的。

                           [in] litemld 指定将要获取成员属性所属自定义层次结构的id,指定-1表示获取指定用户所有自定义层次结构的成员属性信息。

                           [in] litemType 指定将要获取自定义层次结构成员的类型,可以是一个项目也可以是一个文档。如果指定-1那么将获取指定自定义层次的所有类型成员,这种情况成员文档或项目的id不能指定。

                           [in] lMemberld 如果litemType指定的是项目,那么这个参数写项目的id。如果lItemType指定的是文档,那么这个参数指定将要获取属性的文档的项目id。

                           [in] lMemberld2 指定自定义层次结构成员的文档id。如果lItemType是文档,指定-1表示获取所有成员文档的属性信息,如果lItemType是项目,那么这个参数不可用。

                返回值:0 获取失败,指定的自定义层次结构成员不存在。

                              -1 获取失败

                               Otherwise 自定义层次成员的个数

添加自定义层次结构的成员

                函数:BOOL aaApi_AddCustomHierarchyMember(LONG lUserld, LONG litemld, LONG lItemType, LONG lMembeld, LONG lMemberld2)

                介绍:这个函数添加新的成员到某个自定义层次结构上

                参数:[in] lUserld 指定要添加成员的自定义层次结构的用户id,指定0往全局工作台上某个自定义层次结构上添加成员,指定一个负数是往当前用户所在的自定义层次结构上添加成员。

                           [in] lItemld 指定要添加成员的自定义层次结构的id

                           [in] lItemType 指定要添加的成员的类型

                           [in] lMemberld 如果要添加的成员类型是项目,那么这个参数是项目的id。如果要添加的成员类型是文档,那么这个参数是文档所在项目的id。

                           [in] lMemberld 如果要添加的成员那类型是文档,那么这个参数是文档的id。如果要添加的成员类型是项目,那么这个参数忽略。

                返回值:FALSE 添加成员失败

                              TURE 添加成功。

移除自定义层次结构中的指定成员

                函数:aaApi_RemoveCustomHierarchyMember(LONG lUserld, LONG litemld, LONG litemType, LONG lMemberld, LONG lMemberld2)

                介绍:这个函数从指定的自定义层次结构中移除指定的成员

                参数:[in] lUserld 指定要移除成员的自定义层次结构的用户id,指定0往全局工作台上某个自定义层次结构上移除成员,指定-1往当前用户所在的自定义层次结构上移除成员。

                           [in] lItemld 指定要移除成员的自定义层次结构的id

                           [in] lItemType 指定要移除的成员的类型

                           [in] lMemberld 如果要移除的成员类型是项目,那么这个参数是项目的id。如果要移除的成员类型是文档,那么这个参数是文档所在项目的id。

                           [in] lMemberld 如果要移除的成员类型是文档,那么这个参数是文档的id。如果要移除的成员类型是项目,那么这个参数忽略。

                返回值:FALSE 移除指定的成员失败

                              TRUE 移除成功

4.3.3、案例分析

在下面这个案例中,将给大家展示如何将某个用户的私有自定义层次结构显示出来。它的自定义层次结构在ProjectWise中如下图所示:

下面代码将展示如何将这部分信息提取出来,在自己应用程序中展示处上述结构。

首先第一步是将个人自定义层次结构的顶层目录获取出来,然后展示在界面上,也就是将“Personal Folders”下面的“TopOne1”、“TopTwo2”和“TopThree3”顶层节点信息获取出来并展示在我们的平台上。

LONG lRetUserID = aaApi_GetCurrentUserId();
	LONG resNum = aaApi_SelectTopLevelCustomHierarchies(lRetUserID);
	if(-1==resNum)
		return;
	for(long index =0;index<resNum;index++){
		CString strName = aaApi_GetCustomHierarchyStringProperty(UWSP_PROP_NAME,index);
		HTREEITEM treeItem = _MyCustomTree.InsertItem(strName,TVI_ROOT, TVI_LAST);
		LONG lItemId = aaApi_GetCustomHierarchyNumericProperty(UWSP_PROP_CUSTHRCHY,index);
		LONG lPareId = aaApi_GetCustomHierarchyNumericProperty(UWSP_PROP_PARENT,index);  
		CUSTOM_INFO *projItemInfo =new CUSTOM_INFO;
		projItemInfo->BoolExpanded = false;
		projItemInfo->LongItemId = lItemId;
		projItemInfo->longParentId = lPareId;
		_MyCustomTree.SetItemData(treeItem,(long)projItemInfo);
		LONG hasChild = aaApi_GetCustomHierarchyNumericProperty(UWSP_PROP_HASSUBITEMS,index);  
		if(1==hasChild){
			_MyCustomTree.InsertItem(_T("TEST"),treeItem,TVI_LAST);//如果该节点存在一个子节点,则模拟一个临时节点“TEST”,使该节点左侧会出现“+”
		}
	}

接下来第二步,当一个节点存在子节点,我们展开该节点时,将其的子节点信息展示出来。在例子中就是展开“TopOne1”时,将其子节点“SubOne1”和“SubOne2”展示出来。