1 #---------------------------------------------------------------------------- 
   3 # Purpose:      project model for wx.lib.pydocview 
   9 # Copyright:    (c) 2005 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  16 import activegrid
.util
.xmlutils 
as xmlutils
 
  17 from IDE 
import ACTIVEGRID_BASE_IDE
 
  18 if not ACTIVEGRID_BASE_IDE
: 
  19     import activegrid
.model
.basedocmgr 
as basedocmgr
 
  22 #---------------------------------------------------------------------------- 
  24 #---------------------------------------------------------------------------- 
  25 # Always add new versions, never edit the version number 
  26 # This allows you to upgrade the file by checking the version number 
  27 PROJECT_VERSION_050730 
= '10' 
  28 PROJECT_VERSION_050826 
= '11' 
  31 #---------------------------------------------------------------------------- 
  32 # XML Marshalling Methods 
  33 #---------------------------------------------------------------------------- 
  36     version 
= xmlutils
.getAgVersion(fileObject
.name
) 
  37     # most current versions on top 
  38     if version 
== PROJECT_VERSION_050826
: 
  40         if ACTIVEGRID_BASE_IDE
: 
  41             KNOWNTYPES 
= {"ag:project" : Project, "ag:file" : ProjectFile}
 
  43             KNOWNTYPES 
= {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo}
 
  44         project 
= xmlutils
.load(fileObject
.name
, knownTypes
=KNOWNTYPES
, knownNamespaces
=xmlutils
.KNOWN_NAMESPACES
) 
  45     elif version 
== PROJECT_VERSION_050730
: 
  47         project 
= xmlutils
.load(fileObject
.name
, knownTypes
={"project" : Project_10}
) 
  48         project 
= project
.upgradeVersion() 
  50         # assume it is old version without version number 
  52         project 
= xmlutils
.load(fileObject
.name
, knownTypes
={"project" : Project_10}
) 
  54             project 
= project
.upgradeVersion() 
  56             print "Project, unknown version:", version
 
  60         project
._projectDir 
= os
.path
.dirname(fileObject
.name
) 
  61         project
.RelativeToAbsPath() 
  66 def save(fileObject
, project
, productionDeployment
=False): 
  67     if not project
._projectDir
: 
  68         project
._projectDir 
= os
.path
.dirname(fileObject
.name
) 
  69     project
.AbsToRelativePath()  # temporarily change it to relative paths for saving 
  70     if ACTIVEGRID_BASE_IDE
: 
  71         KNOWNTYPES 
= {"ag:project" : Project, "ag:file" : ProjectFile}
 
  73         KNOWNTYPES 
= {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo}
 
  75     savedHomeDir 
= project
.homeDir        
 
  76     if productionDeployment
: 
  77         # for deployments, we don't want an abs path in homeDir since that 
  78         # would tie the app to the current filesystem. So unset it. 
  79         project
.homeDir 
= None 
  81     xmlutils
.save(fileObject
.name
, project
, prettyPrint
=True, knownTypes
=KNOWNTYPES
, knownNamespaces
=xmlutils
.KNOWN_NAMESPACES
) 
  83     if productionDeployment
: 
  84         project
.homeDir 
= savedHomeDir
 
  86     project
.RelativeToAbsPath()  # swap it back to absolute path 
  89 #---------------------------------------------------------------------------- 
  91 #---------------------------------------------------------------------------- 
  93 class BaseProject(object): 
  95     __xmlname__ 
= "project" 
  96     __xmlexclude__ 
= ('fileName', '_projectDir', '_getDocCallback') 
  97     __xmlattributes__ 
= ("_homeDir", "version") 
  98     __xmlrename__ 
= { "_homeDir":"homeDir", "_appInfo":"appInfo" }
 
  99     __xmlflattensequence__ 
= { "_files":("file",) }
 
 100     __xmldefaultnamespace__ 
= xmlutils
.AG_NS_URL
 
 101     __xmlattrnamespaces__ 
= { "ag": ["version", "_homeDir"] }
 
 105         self
.__xmlnamespaces
__ = { "ag" : xmlutils.AG_NS_URL }
 
 106         self
.version 
= PROJECT_VERSION_050826
 
 108         self
._projectDir 
= None  # default for homeDir, set on load 
 109         self
._homeDir 
= None         # user set homeDir for use in calculating relative path 
 110         if not ACTIVEGRID_BASE_IDE
: 
 111             self
._appInfo 
= AppInfo
.AppInfo() 
 116         clone
._files 
= [copy
.copy(file) for file in self
._files
] 
 117         clone
._projectDir 
= self
._projectDir
 
 118         clone
._homeDir 
= self
._homeDir
 
 119         if not ACTIVEGRID_BASE_IDE
: 
 120             clone
._appInfo 
= self
._appInfo
 
 124     def initialize(self
): 
 125         """ Required method for xmlmarshaller """ 
 129     def GetAppInfo(self
): 
 133     def AddFile(self
, filePath
=None, logicalFolder
=None, type=None, name
=None, file=None): 
 134         """ Usage: self.AddFile(filePath, logicalFolder, type, name)  # used for initial generation of object 
 135                    self.AddFile(file=xyzFile)  # normally used for redo/undo 
 136             Add newly created file object using filePath and logicalFolder or given file object 
 139             self
._files
.append(file) 
 141             self
._files
.append(ProjectFile(filePath
, logicalFolder
, type, name
, getDocCallback
=self
._getDocCallback
)) 
 144     def RemoveFile(self
, file): 
 145         self
._files
.remove(file) 
 148     def FindFile(self
, filePath
): 
 150             for file in self
._files
: 
 151                 if file.filePath 
== filePath
: 
 157     def _GetFilePaths(self
): 
 158         return [file.filePath 
for file in self
._files
] 
 161     filePaths 
= property(_GetFilePaths
) 
 164     def _GetLogicalFolders(self
): 
 166         for file in self
._files
: 
 167             if file.logicalFolder 
and file.logicalFolder 
not in folders
: 
 168                 folders
.append(file.logicalFolder
) 
 172     logicalFolders 
= property(_GetLogicalFolders
) 
 175     def _GetPhysicalFolders(self
): 
 177         for file in self
._files
: 
 178             physicalFolder 
= file.physicalFolder
 
 179             if physicalFolder 
and physicalFolder 
not in physicalFolders
: 
 180                 physicalFolders
.append(physicalFolder
) 
 181         return physicalFolders
 
 184     physicalFolders 
= property(_GetPhysicalFolders
) 
 187     def _GetHomeDir(self
): 
 191             return self
._projectDir
 
 194     def _SetHomeDir(self
, parentPath
): 
 195         self
._homeDir 
= parentPath
 
 198     def _IsDefaultHomeDir(self
): 
 199         return (self
._homeDir 
== None) 
 202     isDefaultHomeDir 
= property(_IsDefaultHomeDir
) 
 205     homeDir 
= property(_GetHomeDir
, _SetHomeDir
) 
 208     def GetRelativeFolders(self
): 
 210         for file in self
._files
: 
 211             relFolder 
= file.GetRelativeFolder(self
.homeDir
) 
 212             if relFolder 
and relFolder 
not in relativeFolders
: 
 213                 relativeFolders
.append(relFolder
) 
 214         return relativeFolders
 
 217     def AbsToRelativePath(self
): 
 218         for file in self
._files
: 
 219             file.AbsToRelativePath(self
.homeDir
) 
 222     def RelativeToAbsPath(self
): 
 223         for file in self
._files
: 
 224             file.RelativeToAbsPath(self
.homeDir
) 
 227     #---------------------------------------------------------------------------- 
 228     # BaseDocumentMgr methods 
 229     #---------------------------------------------------------------------------- 
 232     def fullPath(self
, fileName
): 
 233         fileName 
= super(BaseProject
, self
).fullPath(fileName
) 
 235         if os
.path
.isabs(fileName
): 
 238             absPath 
= os
.path
.join(self
.homeDir
, fileName
) 
 240             absPath 
= os
.path
.abspath(fileName
) 
 241         return os
.path
.normpath(absPath
) 
 244     def documentRefFactory(self
, name
, fileType
, filePath
): 
 245         return ProjectFile(filePath
=self
.fullPath(filePath
), type=fileType
, name
=name
, getDocCallback
=self
._getDocCallback
) 
 248     def findAllRefs(self
): 
 252     def GetXFormsDirectory(self
): 
 253         forms 
= self
.findRefsByFileType(basedocmgr
.FILE_TYPE_XFORM
) 
 254         filePaths 
= map(lambda form
: form
.filePath
, forms
) 
 255         xformdir 
= os
.path
.commonprefix(filePaths
) 
 257             xformdir 
= self
.homeDir
 
 261     def setRefs(self
, files
): 
 265     def findRefsByFileType(self
, fileType
): 
 267         for file in self
._files
: 
 268             if fileType 
== file.type: 
 269                 fileList
.append(file) 
 273     def GenerateServiceRefPath(self
, wsdlFilePath
): 
 274         # HACK: temporary solution to getting wsdlag path from wsdl path. 
 276         from WsdlAgEditor 
import WsdlAgDocument
 
 277         ext 
= WsdlAgDocument
.WSDL_AG_EXT
 
 278         for template 
in wx
.GetApp().GetDocumentManager().GetTemplates(): 
 279             if template
.GetDocumentType() == WsdlAgDocument
: 
 280                 ext 
= template
.GetDefaultExtension() 
 282         wsdlAgFilePath 
= os
.path
.splitext(wsdlFilePath
)[0] + ext
 
 283         return wsdlAgFilePath
 
 286     def SetDocCallback(self
, getDocCallback
): 
 287         self
._getDocCallback 
= getDocCallback
 
 288         for file in self
._files
: 
 289             file._getDocCallback 
= getDocCallback
 
 292 if ACTIVEGRID_BASE_IDE
: 
 293     class Project(BaseProject
): 
 296     class Project(BaseProject
, basedocmgr
.BaseDocumentMgr
): 
 300 class ProjectFile(object): 
 302     __xmlexclude__ 
= ('_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',) 
 303     __xmlattributes__ 
= ["filePath", "logicalFolder", "type", "name"] 
 304     __xmldefaultnamespace__ 
= xmlutils
.AG_NS_URL
 
 307     def __init__(self
, filePath
=None, logicalFolder
=None, type=None, name
=None, getDocCallback
=None): 
 308         self
.filePath 
= filePath
 
 309         self
.logicalFolder 
= logicalFolder
 
 312         self
._getDocCallback 
= getDocCallback
 
 313         self
._docCallbackCacheReturnValue 
= None 
 314         self
._docModelCallbackCacheReturnValue 
= None 
 318     def _GetDocumentModel(self
): 
 319         # possible bug is if document gets replaced outside of IDE, where we'll return previous doc. 
 320         # originally added a timestamp check but that increased the time again to 4x 
 321         if self
._docModelCallbackCacheReturnValue
:  # accelerator for caching document, got 4x speed up. 
 322             return self
._docModelCallbackCacheReturnValue
 
 324         if self
._getDocCallback
: 
 325             self
._docCallbackCacheReturnValue
, self
._docModelCallbackCacheReturnValue 
= self
._getDocCallback
(self
.filePath
) 
 326             return self
._docModelCallbackCacheReturnValue
 
 331     document 
= property(_GetDocumentModel
) 
 334     def _GetDocument(self
): 
 335         # Hack, just return the IDE document wrapper that corresponds to the runtime document model 
 336         # callers should have called ".document" before calling ".ideDocument" 
 337         if self
._docCallbackCacheReturnValue
:  # accelerator for caching document, got 4x speed up. 
 338             return self
._docCallbackCacheReturnValue
 
 342     ideDocument 
= property(_GetDocument
) 
 345     def _typeEnumeration(self
): 
 346         return basedocmgr
.FILE_TYPE_LIST
 
 349     def _GetPhysicalFolder(self
): 
 352             dir = os
.path
.dirname(self
.filePath
) 
 354                 dir = dir.replace(os
.sep
, '/')  # require '/' as delimiter 
 358     physicalFolder 
= property(_GetPhysicalFolder
) 
 361     def GetRelativeFolder(self
, parentPath
): 
 362         parentPathLen 
= len(parentPath
) 
 366             dir = os
.path
.dirname(self
.filePath
) 
 367             if dir.startswith(parentPath
): 
 368                 dir = "." + dir[parentPathLen
:]  # convert to relative path 
 370                 dir = dir.replace(os
.sep
, '/')  # always save out with '/' as path separator for cross-platform compatibility. 
 374     def AbsToRelativePath(self
, parentPath
): 
 375         """ Used to convert path to relative path for saving (disk format) """ 
 376         parentPathLen 
= len(parentPath
) 
 378         if self
.filePath
.startswith(parentPath
): 
 379             self
.filePath 
= "." + self
.filePath
[parentPathLen
:]  # convert to relative path 
 381                 self
.filePath 
= self
.filePath
.replace(os
.sep
, '/')  # always save out with '/' as path separator for cross-platform compatibility. 
 383             pass    # not a decendant of project, use absolute path 
 386     def RelativeToAbsPath(self
, parentPath
): 
 387         """ Used to convert path to absolute path (for any necessary disk access) """ 
 388         if self
.filePath
.startswith("."):  # relative to project file 
 389             self
.filePath 
= os
.path
.normpath(os
.path
.join(parentPath
, self
.filePath
)) 
 392     #---------------------------------------------------------------------------- 
 393     # BaseDocumentMgr methods 
 394     #---------------------------------------------------------------------------- 
 397         # HACK: temporary solution. 
 399         import wx
.lib
.docview
 
 401             docMgr 
= wx
.GetApp().GetDocumentManager() 
 403             doc 
= docMgr
.CreateDocument(self
.filePath
, docMgr
.GetFlags()|wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE|wx
.lib
.docview
.DOC_NO_VIEW
) 
 404             if (doc 
== None):  # already open 
 405                 docs 
= docMgr
.GetDocuments() 
 407                     if d
.GetFilename() == self
.filePath
: 
 414     def _GetLocalServiceProcessName(self
): 
 415         # HACK: temporary solution to getting process name from wsdlag file. 
 416         return self
._GetDoc
().GetModel().processName
 
 419     processName 
= property(_GetLocalServiceProcessName
) 
 422     def _GetStateful(self
): 
 423         # HACK: temporary solution to getting stateful from wsdlag file. 
 424         return self
._GetDoc
().GetModel().stateful
 
 427     def _SetStateful(self
, stateful
): 
 428         # HACK: temporary solution to setting stateful from wsdlag file. 
 429         self
._GetDoc
().GetModel().stateful 
= stateful
 
 432     stateful 
= property(_GetStateful
, _SetStateful
) 
 435     def _GetLocalServiceCodeFile(self
): 
 436         # HACK: temporary solution to getting class name from wsdlag file. 
 437         return self
._GetDoc
().GetModel().localServiceCodeFile
 
 440     def _SetLocalServiceCodeFile(self
, codefile
): 
 441         # HACK: temporary solution to setting class name from wsdlag file. 
 442         self
._GetDoc
().GetModel().localServiceCodeFile 
= codefile
 
 445     localServiceCodeFile 
= property(_GetLocalServiceCodeFile
, _SetLocalServiceCodeFile
) 
 448     def _GetLocalServiceClassName(self
): 
 449         # HACK: temporary solution to getting class name from wsdlag file. 
 450         return self
._GetDoc
().GetModel().localServiceClassName
 
 453     def _SetLocalServiceClassName(self
, className
): 
 454         # HACK: temporary solution to setting class name from wsdlag file. 
 455         self
._GetDoc
().GetModel().localServiceClassName 
= className
 
 458     localServiceClassName 
= property(_GetLocalServiceClassName
, _SetLocalServiceClassName
) 
 462 # only activate this code if we programatically need to access these values 
 463 ##    def _GetRssServiceBaseURL(self): 
 464 ##        return self._GetDoc().GetModel().rssServiceBaseURL 
 467 ##    def _SetRssServiceBaseURL(self, baseURL): 
 468 ##        self._GetDoc().GetModel().rssServiceBaseURL = baseURL 
 471 ##    rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL) 
 474 ##    def _GetRssServiceRssVersion(self): 
 475 ##        return self._GetDoc().GetModel().rssServiceRssVersion 
 478 ##    def _SetRssServiceRssVersion(self, rssVersion): 
 479 ##        self._GetDoc().GetModel().rssServiceRssVersion = rssVersion 
 482 ##    rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion) 
 485     def _GetServiceRefServiceType(self
): 
 486         # HACK: temporary solution to getting service type from wsdlag file. 
 487         model 
= self
._GetDoc
().GetModel() 
 488         if hasattr(model
, 'serviceType'): 
 489             return model
.serviceType
 
 494     def _SetServiceRefServiceType(self
, serviceType
): 
 495         # HACK: temporary solution to getting service type from wsdlag file. 
 496         self
._GetDoc
().GetModel().serviceType 
= serviceType
 
 499     serviceType 
= property(_GetServiceRefServiceType
, _SetServiceRefServiceType
) 
 502     def getExternalPackage(self
): 
 503         # HACK: temporary solution to getting custom code filename from wsdlag file. 
 504         import activegrid
.server
.deployment 
as deploymentlib    
 
 506         appInfo 
= self
._GetDoc
().GetAppInfo() 
 508         if appInfo
.language 
== None: 
 509             language 
= deploymentlib
.LANGUAGE_DEFAULT
 
 511             language 
= appInfo
.language
 
 513         if language 
== deploymentlib
.LANGUAGE_PYTHON
: 
 515         elif language 
== deploymentlib
.LANGUAGE_PHP
: 
 517         pyFilename 
= self
.name 
+ suffix
 
 518         return self
._GetDoc
().GetAppDocMgr().fullPath(pyFilename
) 
 521 #---------------------------------------------------------------------------- 
 523 #---------------------------------------------------------------------------- 
 526     """ Version 1.0, kept for upgrading to latest version.  Over time, this should be deprecated. """ 
 527     __xmlname__ 
= "project" 
 528     __xmlrename__ 
= { "_files":"files"}
 
 529     __xmlexclude__ 
= ('fileName',) 
 530     __xmlattributes__ 
= ["version"] 
 534         self
.version 
= PROJECT_VERSION_050730
 
 538     def initialize(self
): 
 539         """ Required method for xmlmarshaller """ 
 543     def upgradeVersion(self
): 
 544         currModel 
= Project() 
 545         for file in self
._files
: 
 546             currModel
._files
.append(ProjectFile(file))