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())