def loadCache(obj, user=None):
    if isinstance(obj, dict):
        if 'applet' in obj:
            try:
                obj["applet"]["responseDates"] = responseDateList(
                    obj['applet'].get('_id', '').split('applet/')[-1],
                    user.get('_id'),
                    user
                )
            except:
                obj["applet"]["responseDates"] = []
        return(obj)
    else:
        cache = json_util.loads(obj)
        if 'applet' in cache:
            try:
                cache["applet"]["responseDates"] = responseDateList(
                    cache['applet'].get('_id', '').split('applet/')[-1],
                    user.get('_id'),
                    user
                )
            except:
                cache["applet"]["responseDates"] = []
        return(
            {
                k: v for k, v in cache.items() if k!="prov:generatedAtTime"
            } if isinstance(cache, dict) else cache
        )
def formatLdObject(obj,
                   mesoPrefix='folder',
                   user=None,
                   keepUndefined=False,
                   dropErrors=False,
                   refreshCache=False,
                   responseDates=False):
    """
    Function to take a compacted JSON-LD Object within a Girder for Mindlogger
    database and return an exapanded JSON-LD Object including an _id.

    :param obj: Compacted JSON-LD Object
    :type obj: dict or list
    :param mesoPrefix: Girder for Mindlogger entity type, defaults to 'folder'
                       if not provided
    :type mesoPrefix: str
    :param user: User making the call
    :type user: User
    :param keepUndefined: Keep undefined properties
    :type keepUndefined: bool
    :param dropErrors: Return `None` instead of raising an error for illegal
        JSON-LD definitions.
    :type dropErrors: bool
    :param refreshCache: Refresh from Dereferencing URLs?
    :type refreshCache: bool
    :param responseDates: Include list of ISO date strings of responses
    :type responseDates: bool
    :returns: Expanded JSON-LD Object (dict or list)
    """
    from girderformindlogger.models import pluralize

    refreshCache = False if refreshCache is None else refreshCache

    try:
        if obj is None:
            return (None)
        if isinstance(obj, dict):
            oc = obj.get("cached")
            if all([not refreshCache, oc is not None]):
                return (loadCache(oc))
            if 'meta' not in obj.keys():
                return (_fixUpFormat(obj))
        mesoPrefix = camelCase(mesoPrefix)
        if type(obj) == list:
            return (_fixUpFormat([
                formatLdObject(o,
                               mesoPrefix,
                               refreshCache=refreshCache,
                               user=user) for o in obj if o is not None
            ]))
        if not type(obj) == dict and not dropErrors:
            raise TypeError("JSON-LD must be an Object or Array.")
        newObj = obj.get('meta', obj)
        newObj = newObj.get(mesoPrefix, newObj)
        newObj = expand(newObj, keepUndefined=keepUndefined)
        if type(newObj) == list and len(newObj) == 1:
            try:
                newObj = newObj[0]
            except:
                raise ValidationException(str(newObj))
        if type(newObj) != dict:
            newObj = {}
        objID = str(obj.get('_id', 'undefined'))
        if objID == 'undefined':
            raise ResourcePathNotFound()
        newObj['_id'] = "/".join([snake_case(mesoPrefix), objID])
        if mesoPrefix == 'applet':
            protocolUrl = obj.get('meta', {}).get('protocol', obj).get(
                'http://schema.org/url',
                obj.get('meta', {}).get('protocol', obj).get('url'))
            protocol = ProtocolModel().getFromUrl(
                protocolUrl,
                'protocol',
                user,
                thread=False,
                refreshCache=refreshCache
            )[0] if protocolUrl is not None else {}
            protocol = formatLdObject(protocol,
                                      'protocol',
                                      user,
                                      refreshCache=refreshCache)
            applet = {}
            applet['activities'] = protocol.pop('activities', {})
            applet['items'] = protocol.pop('items', {})
            applet['protocol'] = {
                key: protocol.get('protocol', protocol.get('activitySet',
                                                           {})).pop(key)
                for key in
                ['@type', '_id', 'http://schema.org/url', 'schema:url', 'url']
                if key in list(protocol.get('protocol', {}).keys())
            }
            applet['applet'] = {
                **protocol.pop('protocol', {}),
                **obj.get('meta', {}).get(mesoPrefix, {}), '_id':
                "/".join([snake_case(mesoPrefix), objID]),
                'url':
                "#".join(
                    [obj.get('meta', {}).get('protocol', {}).get("url", "")])
            }
            createCache(obj, applet, 'applet', user)
            if responseDates:
                try:
                    applet["applet"]["responseDates"] = responseDateList(
                        obj.get('_id'), user.get('_id'), user)
                except:
                    applet["applet"]["responseDates"] = []
            return (applet)
        elif mesoPrefix == 'protocol':
            protocol = {'protocol': newObj, 'activities': {}, "items": {}}
            activitiesNow = set()
            itemsNow = set()
            try:
                protocol = componentImport(newObj,
                                           deepcopy(protocol),
                                           user,
                                           refreshCache=refreshCache)
            except:
                print("636")
                protocol = componentImport(newObj,
                                           deepcopy(protocol),
                                           user,
                                           refreshCache=True)
            newActivities = [
                a for a in protocol.get('activities', {}).keys()
                if a not in activitiesNow
            ]
            newItems = [
                i for i in protocol.get('items', {}).keys()
                if i not in itemsNow
            ]
            while (any([len(newActivities), len(newItems)])):
                activitiesNow = set(protocol.get('activities', {}).keys())
                itemsNow = set(protocol.get('items', {}).keys())
                for activityURL in newActivities:
                    activity = protocol['activities'][activityURL]
                    activity = activity.get('meta',
                                            {}).get('activity', activity)
                    try:
                        protocol = componentImport(deepcopy(activity),
                                                   deepcopy(protocol),
                                                   user,
                                                   refreshCache=refreshCache)
                    except:
                        print("670")
                        protocol = componentImport(deepcopy(activity),
                                                   deepcopy(protocol),
                                                   user,
                                                   refreshCache=True)
                for itemURL in newItems:
                    activity = protocol['items'][itemURL]
                    activity = activity.get('meta', {}).get('screen', activity)
                    try:
                        protocol = componentImport(deepcopy(activity),
                                                   deepcopy(protocol),
                                                   user,
                                                   refreshCache=refreshCache)
                    except:
                        print("691")
                        protocol = componentImport(deepcopy(activity),
                                                   deepcopy(protocol),
                                                   user,
                                                   refreshCache=True)
                newActivities = list(
                    set(protocol.get('activities', {}).keys()) - activitiesNow)
                newItems = list(
                    set(protocol.get('items', {}).keys()) - itemsNow)
            return (_fixUpFormat(protocol))
        else:
            return (_fixUpFormat(newObj))
    except:
        if refreshCache == False:
            return (_fixUpFormat(
                formatLdObject(obj,
                               mesoPrefix,
                               user,
                               keepUndefined,
                               dropErrors,
                               refreshCache=False,
                               responseDates=responseDates)))
        import sys, traceback
        print(sys.exc_info())
        print(traceback.print_tb(sys.exc_info()[2]))
Esempio n. 3
0
def formatLdObject(obj,
                   mesoPrefix='folder',
                   user=None,
                   keepUndefined=False,
                   dropErrors=False,
                   refreshCache=False,
                   responseDates=False):
    """
    Function to take a compacted JSON-LD Object within a Girder for Mindlogger
    database and return an exapanded JSON-LD Object including an _id.

    :param obj: Compacted JSON-LD Object
    :type obj: dict or list
    :param mesoPrefix: Girder for Mindlogger entity type, defaults to 'folder'
                       if not provided
    :type mesoPrefix: str
    :param user: User making the call
    :type user: User
    :param keepUndefined: Keep undefined properties
    :type keepUndefined: bool
    :param dropErrors: Return `None` instead of raising an error for illegal
        JSON-LD definitions.
    :type dropErrors: bool
    :param refreshCache: Refresh from Dereferencing URLs?
    :type refreshCache: bool
    :param responseDates: Include list of ISO date strings of responses
    :type responseDates: bool
    :returns: Expanded JSON-LD Object (dict or list)
    """
    from girderformindlogger.models import pluralize

    refreshCache = False if refreshCache is None else refreshCache

    try:
        if obj is None:
            return (None)
        if isinstance(obj, dict):
            oc = obj.get("cached")
            if all([not refreshCache, oc is not None]):
                return (loadCache(oc))
            if 'meta' not in obj.keys():
                return (_fixUpFormat(obj))
        mesoPrefix = camelCase(mesoPrefix)
        if type(obj) == list:
            return (_fixUpFormat([
                formatLdObject(o,
                               mesoPrefix,
                               refreshCache=refreshCache,
                               user=user) for o in obj if o is not None
            ]))
        if not type(obj) == dict and not dropErrors:
            raise TypeError("JSON-LD must be an Object or Array.")
        newObj = obj.get('meta', obj)
        newObj = newObj.get(mesoPrefix, newObj)

        if not obj.get('loadedFromSingleFile', False):
            newObj = expand(newObj, keepUndefined=keepUndefined)

        if type(newObj) == list and len(newObj) == 1:
            try:
                newObj = newObj[0]
            except:
                raise ValidationException(str(newObj))
        if type(newObj) != dict:
            newObj = {}
        objID = str(obj.get('_id', 'undefined'))
        if objID == 'undefined':
            raise ResourcePathNotFound('unable to load object')
        newObj['_id'] = "/".join([snake_case(mesoPrefix), objID])
        if mesoPrefix == 'applet':
            protocolUrl = obj.get('meta', {}).get('protocol', obj).get(
                'http://schema.org/url',
                obj.get('meta', {}).get('protocol', obj).get('url'))

            # get protocol data from id
            protocol = None
            protocolId = obj.get('meta', {}).get('protocol',
                                                 {}).get('_id',
                                                         '').split('/')[-1]
            if protocolId:
                cache = ProtocolModel().getCache(protocolId)
                if cache:
                    protocol = loadCache(cache)

            if protocolUrl is not None and not protocol:
                # get protocol from url
                protocol = ProtocolModel().getFromUrl(
                    protocolUrl,
                    'protocol',
                    user,
                    thread=False,
                    refreshCache=refreshCache)[0]

            # format protocol data
            protocol = formatLdObject(protocol,
                                      'protocol',
                                      user,
                                      refreshCache=refreshCache)

            applet = {}
            applet['activities'] = protocol.pop('activities', {})
            applet['items'] = protocol.pop('items', {})
            applet['protocol'] = {
                key: protocol.get('protocol', protocol.get('activitySet',
                                                           {})).pop(key)
                for key in
                ['@type', '_id', 'http://schema.org/url', 'schema:url', 'url']
                if key in list(protocol.get('protocol', {}).keys())
            }
            applet['applet'] = {
                **protocol.pop('protocol', {}),
                **obj.get('meta', {}).get(mesoPrefix, {}), '_id':
                "/".join([snake_case(mesoPrefix), objID]),
                'url':
                "#".join(
                    [obj.get('meta', {}).get('protocol', {}).get("url", "")])
            }

            if 'appletName' in obj and obj['appletName']:
                suffix = obj['appletName'].split('/')[-1]
                inserted = False

                candidates = ['prefLabel', 'altLabel']
                for candidate in candidates:
                    for key in applet['applet']:
                        if not inserted and str(key).endswith(
                                candidate) and len(
                                    applet['applet'][key]) and len(
                                        applet['applet'][key][0].get(
                                            '@value', '')):
                            if len(suffix):
                                applet['applet'][key][0]['@value'] += (' ' +
                                                                       suffix)

                            if not len(applet['applet']
                                       ['url']):  # for development
                                applet['applet'][key][0][
                                    '@value'] += ' ( single-file )'

                            AppletModel().update({'_id': obj['_id']}, {
                                '$set': {
                                    'displayName':
                                    applet['applet'][key][0]['@value']
                                }
                            })

                            inserted = True
            createCache(obj, applet, 'applet', user)
            if responseDates:
                try:
                    applet["applet"]["responseDates"] = responseDateList(
                        obj.get('_id'), user.get('_id'), user)
                except:
                    applet["applet"]["responseDates"] = []
            return (applet)
        elif mesoPrefix == 'protocol':
            protocol = {'protocol': newObj, 'activities': {}, "items": {}}

            if obj.get('loadedFromSingleFile', False):
                activities = list(ActivityModel().find({
                    'meta.protocolId':
                    '{}/{}'.format(MODELS()['protocol']().name, obj['_id'])
                }))
                items = list(ScreenModel().find({
                    'meta.protocolId':
                    '{}/{}'.format(MODELS()['protocol']().name, obj['_id'])
                }))

                for activity in activities:
                    formatted = formatLdObject(activity, 'activity', user)
                    protocol['activities'][formatted['@id']] = formatted
                for item in items:
                    formatted = formatLdObject(item, 'screen', user)
                    protocol['items'][formatted['@id']] = formatted
            else:
                try:
                    protocol = componentImport(newObj,
                                               deepcopy(protocol),
                                               user,
                                               refreshCache=refreshCache)
                except:
                    print("636")
                    protocol = componentImport(newObj,
                                               deepcopy(protocol),
                                               user,
                                               refreshCache=True)

                newActivities = protocol.get('activities', {}).keys()
                newItems = protocol.get('items', {}).keys()

                while (any([len(newActivities), len(newItems)])):
                    activitiesNow = set(protocol.get('activities', {}).keys())
                    itemsNow = set(protocol.get('items', {}).keys())
                    for activityURL in newActivities:
                        activity = protocol['activities'][activityURL]
                        activity = activity.get('meta',
                                                {}).get('activity', activity)
                        try:
                            protocol = componentImport(
                                deepcopy(activity),
                                deepcopy(protocol),
                                user,
                                refreshCache=refreshCache)
                        except:
                            print("670")
                            protocol = componentImport(deepcopy(activity),
                                                       deepcopy(protocol),
                                                       user,
                                                       refreshCache=True)
                    for itemURL in newItems:
                        activity = protocol['items'][itemURL]
                        activity = activity.get('meta',
                                                {}).get('screen', activity)
                        try:
                            protocol = componentImport(
                                deepcopy(activity),
                                deepcopy(protocol),
                                user,
                                refreshCache=refreshCache)
                        except:
                            print("691")
                            protocol = componentImport(deepcopy(activity),
                                                       deepcopy(protocol),
                                                       user,
                                                       refreshCache=True)
                    newActivities = list(
                        set(protocol.get('activities', {}).keys()) -
                        activitiesNow)
                    newItems = list(
                        set(protocol.get('items', {}).keys()) - itemsNow)

            formatted = _fixUpFormat(protocol)

            createCache(obj, formatted, 'protocol')
            return formatted
        else:
            return (_fixUpFormat(newObj))
    except:
        if refreshCache == False:
            return (_fixUpFormat(
                formatLdObject(obj,
                               mesoPrefix,
                               user,
                               keepUndefined,
                               dropErrors,
                               refreshCache=True,
                               responseDates=responseDates)))
        import sys, traceback
        print(sys.exc_info())
        print(traceback.print_tb(sys.exc_info()[2]))
Esempio n. 4
0
    def getOwnApplets(
        self,
        role,
        ids_only=False,
        unexpanded=False,
        refreshCache=False
    ):
        from bson.objectid import ObjectId
        from girderformindlogger.utility.jsonld_expander import loadCache

        from girderformindlogger.utility.response import responseDateList

        reviewer = self.getCurrentUser()
        if reviewer is None:
            raise AccessException("You must be logged in to get user applets.")
        role = role.lower()
        if role not in USER_ROLES.keys():
            raise RestException(
                'Invalid user role.',
                'role'
            )

        applet_ids = reviewer.get('applets', {}).get(role, [])

        if ids_only:
            return applet_ids
        applets = [AppletModel().load(ObjectId(applet_id), AccessType.READ) for applet_id in applet_ids]

        if unexpanded:
            return([{
                'applet': AppletModel().unexpanded(applet)
            } for applet in applets])

        try:
            result = []
            for applet in applets:
                if applet.get('cached'):
                    formatted = {
                        **jsonld_expander.formatLdObject(
                            applet,
                            'applet',
                            reviewer,
                            refreshCache=refreshCache,
                            responseDates=False
                        ),
                        "users": AppletModel().getAppletUsers(applet, reviewer),
                        "groups": AppletModel().getAppletGroups(
                            applet,
                            arrayOfObjects=True
                        )
                    } if role in ["coordinator", "manager"] else {
                        **jsonld_expander.formatLdObject(
                            applet,
                            'applet',
                            reviewer,
                            refreshCache=refreshCache,
                            responseDates=(role=="user")
                        ),
                        "groups": [
                            group for group in AppletModel().getAppletGroups(applet).get(
                                role
                            ) if ObjectId(
                                group
                            ) in [
                                *reviewer.get('groups', []),
                                *reviewer.get('formerGroups', []),
                                *[invite['groupId'] for invite in [
                                    *reviewer.get('groupInvites', []),
                                    *reviewer.get('declinedInvites', [])
                                ]]
                            ]
                        ]
                    }

                    try:
                        formatted["applet"]["responseDates"] = responseDateList(
                            applet.get('_id'),
                            reviewer.get('_id'),
                            reviewer
                        )
                    except:
                        formatted["applet"]["responseDates"] = []
                    result.append(formatted)

            return(result)
        except:
            import sys, traceback
            print(sys.exc_info())
            return([])