Display all scripting code of window and template components

Step 1: Get the context. I think this is familiar.

If the context cant be located in the script console you may have a flag that is odd.
print the system.util.getSystemFlags() and add the resulting integer to [DESIGNER_FLAG, 3] list.

current_flag = system.util.getSystemFlags()
ctx = self.resolveDesignerContext
# If False assumes the client context.
if current_flag not in [DESIGNER_FLAG, 3]:

After ensuring you have the context this should work. Update the path to your context and have fun with the joke.

Step 2:

from com.inductiveautomation.factorypmi.application.binding.action import ActionAdapter


class ScriptFinder:
	
	def __init__(self, context):
		
		self.context = context
		if not hasattr(self.context, 'getProject'):
			raise Exception(self.getInvalidContextError(context))
	
	def getProjectResources(self):
		"""Return all project Resources."""
		return self.context.getProject().getResources()
		
	def getInvalidResourceTypeError(self, resource_type):
		"""Return formatted error message."""
		return 'Invalid Resource Type "%s". Options are: %s || %s.' % (
			resource_type, self.getWindowResourceType(), self.getTemplateResourceType())

	def getInvalidContextError(self, context):
		"""Return formatted error message."""
		return 'Invalid Context Reference "%s". Hint Context must support getProject method' % str(type(context))
		
	def objectSearch(self, fpmiObject, array):
		"""
		NOTES: 
		: This method takes an JComponent
		: and an array reference it will recursivley 
		: walk the component chain accumulating members until 
		: reaching the last container.
		
		Arg(s):
		: [  fpmiObject ]  DataType: JComponent
		:	Example: Jframe, Jdialog, FMPI Root Container,
		: [    array    ]  DataType: list
		:	Example: []
		"""
		try:
			for component in fpmiObject.getComponents():
				array.append(component)
				self.objectSearch(component, array)
		except AttributeError:
			return

	def getAllComponentsForFpmiObject(self, fpmiObject):
		"""
		NOTES: 
		: Method takes a top level jcomponent and calls the
		: getComponents method. If the result is an AttributeError
		: the array is returned. If there are results both the array
		: reference and the component are passed to a recursive function
		: that will go throught the component chain.
		
		Arg(s):
		: [  fpmiObject  ]  DataType: JComponent
		: 	Example: Jframe, Jdialog, FMPI Root Container,
		"""
		components_array = []
		try:
			for component in fpmiObject.getComponents():
				components_array.append(component)
				self.objectSearch(component, components_array)
		except AttributeError:
			pass		
		return components_array
	
	def getProjectResourcesByType(self, resource_type):
		"""
		NOTES:
		: Filter resource array on type.
		Arg(s):
		: [resource_type]  DataType: String
		:	Example: "window", "component-template"
		"""
		return [
			resource for resource in self.getProjectResources() 
			if resource.getResourceType() == resource_type
		]
		
	def getWindowResourceType(self):
		"""Returns windows resource type."""
		return 'window'
	
	def getTemplateResourceType(self):
		"""Returns template resource type."""
		return 'component-template'	
	
	
	def getSerializedReferenceFromResource(self, resource_type):
		"""
		NOTES:
		: Returns a reusable function for the deserialization of 
		: the requested types. Reduces process overhead for iterative
		: resource assessment.
		
		Arg(s):
		: [resource_type]  DataType: String
		:  Example: "window", "component-template"
		"""
	
		deserializer = self.context.createDeserializer()
		deserialize = deserializer.deserialize
		
		def windowInner(resource):
			"""
			NOTES:
			: Inner Function that supports deserialization of window 
			: resources. The window root objects support a different method than
			: templates for retrieving the bytesArray.
			
			Arg(s)
			:  [ resource ]  DataType: <type 'com.inductiveautomation.ignition.common.project.ProjectResource'>
			"""
			code = deserialize(resource.getData()).getRootObjects()[0].getSerializedCode()
			return deserialize(code).getRootObjects()[0]
		
		def templateInner(resource):
			"""
			NOTES:
			: Inner Function that supports deserialization of template
			: resources. The template root objects support a different method than
			: templates for retrieving the bytesArray.
			
			Arg(s)
			:  [ resource ]  DataType: <type 'com.inductiveautomation.ignition.common.project.ProjectResource'>
			:
			"""
			code = deserialize(resource.getData()).getRootObjects()[0].getSerializedBytes()
			return deserialize(code).getRootObjects()[0]
		
		if resource_type == self.getWindowResourceType():
			return windowInner
		elif resource_type == self.getTemplateResourceType():
			return templateInner
		raise Exception(self.getInvalidResourceTypeError(resource_type))
			
	
	def getDeSerializedResources(self, resource_type, resource_array):
		"""
		NOTES:
		: Return an array of deserialized project resoures.
		
		Arg(s)
		: [   resource_type  ]  DataType: String
		:  Example: "window", "component-template"
		: [  resource_array  ]  DataType: list
		:  Example: []
		"""
		deserializer = self.getSerializedReferenceFromResource(resource_type)
		return [deserializer(resource) for resource in resource_array]
	
	
	def getComponentAdapterGetter(self, resource):
		"""
		NOTES:
		: Returns an uncalled method for use in iteration.
		: This method gets all adapteres associated for the
		: component passed in.
		
		Arg(s)
		: [   resource  ]  DataType: <type 'com.inductiveautomation.ignition.common.project.ProjectResource'>
		:  
		"""		
		return resource.getInteractionController().getAllAdaptersForTarget
	
	
	def getValidResourceType(self):
		"""Returns array of valid resource types."""
		return [self.getWindowResourceType(), self.getTemplateResourceType()]
	
	def isResourceTypeValid(self, resource_type):
		"""Checks resource type for validity."""
		return resource_type in self.getValidResourceType()
	
	def getObjectName(self, resource):
		"""Return object name."""
		return str(resource.getTitle() if hasattr(resource, 'getTitle') else resource.getName())
		
	def getActionAdatpersforComponent(self, resource, component):
		"""Returns filtered array of Action Adapters for component."""
		adapterGetter = self.getComponentAdapterGetter(resource)
		return [adapter for adapter in adapterGetter(component) if isinstance(adapter, ActionAdapter)]
	
	
	def getJythonCodeForResourceComponents(self, resource_type):
		"""
		NOTES:
		: Returns a dictionary of resource: {components: {code: ''}}.
		: Process acquires resources of specified type and iterates
		: over all components action adapters.
		
		Arg(s)
		: [   resource_type  ]  DataType: String
		:  Example: "window", "component-template"
		"""	
		# Test validity of type.
		if self.isResourceTypeValid(resource_type):
			resource_component_code_map = {}
			#Acquire resource data for type.
			resources =  self.getProjectResourcesByType(resource_type)
			# Iterate through deserialized resources.
			for resource in self.getDeSerializedResources(resource_type, resources):
				resource_name = self.getObjectName(resource)
				# Get all components.
				components = self.getAllComponentsForFpmiObject(resource)
				if components:
					resource_component_code_map[resource_name] = {}
					#Iterate over component.
					for component in components:
						component_name = self.getObjectName(component)
						# Get adapters for component and iterate filtering on action adapters.
						for adapter in self.getActionAdatpersforComponent(resource, component):
							# Create entry in dictionary if not present.
							if component_name not in resource_component_code_map[resource_name]:
								resource_component_code_map[resource_name][component_name] = {}
							# Get code from action adapter.
							code = adapter.getJythonCode()
							# Get component method associated with the code.
							method_name = adapter.getMethodDescriptor().getName()
							# Update resource map.
							resource_component_code_map[resource_name][component_name][method_name] = code
							
			return resource_component_code_map
		
		raise Exception(self.getInvalidResourceTypeError(resource_type))
		return {}

	def getAllWindowsAllComponentsJythonCode(self):
		""" Returns dictionary of window resource: {components: {code: ''}}."""
		return self.getJythonCodeForResourceComponents(self.getWindowResourceType())

	def getAllTemplatesAllComponentsJythonCode(self):
		""" Returns dictionary of template resource: {components: {code: ''}}."""
		return self.getJythonCodeForResourceComponents(self.getTemplateResourceType())

	def prettyPrint(self, output):
		print system.util.jsonEncode(output, 4)



context = project.Resources.Context.getContext() # <- this must be correct
sf = ScriptFinder(context)

sf.prettyPrint(sf.getAllWindowsAllComponentsJythonCode())

sf.prettyPrint(sf.getAllTemplatesAllComponentsJythonCode())
5 Likes