Skip to main content

OpenICOM: A JPA Framework for Integrated Collaboration Environments: Part 2, Extension Modules

July 7, 2013

by Laura Dragan, Kenneth Baclawski, Eric S. Chan, Patrick Durusau, Peter Yim

Abstract

This is the second article in a series about ICOM. In this article we describe the extension modules for AddressBook, Presence, FreeBusy, Calendar, Task, Conference, and Forum. ICOM is a modular framework for integration of collaboration services, and while the core part of the model is essential for establishing the basis for ICOM, a system will usually need some or all of the extension modules to support particular use case scenarios. In practice, the concepts in the extension modules are the ones that developers and users interact with most often. Throughout the article we provide examples and code snippets, to guide readers in working with ICOM.

Introduction

Organizations need to integrate their collaboration services with business applications in order to enable contextual collaboration within an end-to-end business process, such as customer relationship management, procurement, performance, and project management, to improve business efficiency. Typically organizations have already incrementally deployed a mix of disjoint collaboration tools. As a result, they face technical obstacles and high costs to integrate these disjoint tools and the data each tool produces. To solve this problem, various collaboration vendors have attempted to create unified platforms in order to build a single collaboration environment which provides support for the full range of collaboration activities. However, integrating these vendor-specific platforms is still difficult as they lack a standard model, interfaces and protocols. Without a standard collaboration model that can represent the complete range of collaboration activities, customers, ISVs, and integrators face a difficult challenge to build contextual collaboration environments using service components from multiple vendors.

The OASIS ICOM Technical Committee was chartered to provide a standard model for collaboration tools, aimed at solving the integration problem, while allowing vendors to provide their own unique services to their customers. ICOM consists of a core model and extension modules. The ICOM core model covers the terminology and services that are common to the majority of collaboration tools. The ICOM extension modules cover the terminology and services that depend on the particular collaboration tools. We begin with a brief introduction to the ICOM core as background, and then we describe each of the extension modules. For more detail concerning the ICOM core see the first part of this series.

ICOM Core Background

Most of the ICOM classes are derived from the Entity class. This class provides for a persistent identifier and access control. Objects that will be stored in a database should be Entity objects. This is consistent with entity-relationship modeling and with object-relational mapping frameworks such as JPA.

The ICOM core model is divided into three main branches: Subject, Artifact and Scope. The Subject branch defines Role, Group, and Actor classes, to represent entities that have rights to perform actions on other entities. The Artifact branch includes generic components like Folder, Document, and Message, and more specialized ones like HeterogeneousFolder which is a common type of Folder, and UnifiedMessage which is a common type of Message. An artifact is a result of a communication, cooperation, content creation, or in general a collaboration activity. The Scope branch brings together the concepts from Subject and Artifact. It defines Community and Space, where Communities aggregate Actors and Spaces aggregate Artifacts.

ICOM Extensions

The extension modules provided by ICOM cover the most common areas of collaboration applications:

  • Contact management for information about people and organizations.
  • Time and schedule management
  • Task management
  • Communication and meeting management

Extensions to ICOM are encouraged, but to ensure interoperability with other ICOM-compliant systems, such extensions must be submitted to the ICOM TC for discussion and standardization in later versions.

Most of the extension modules described below define concrete subclasses of the class Folder, and the Artifacts that they contain. However, this is not always true. For example, Presence and FreeBusy extension modules do not include any subclasses of either Folder or Artifact.

In the rest of this article, we describe each of the extension modules in detail, including both the classes and the relationships between them. To illustrate the design of the extension modules, we will use the following simple running example:

Jamie is working for a large company, where he is responsible for managing a small team of people working on multiple customer projects in parallel. He receives large quantities of emails on a wide array of topics, from team members, colleagues from other parts of the company, project partners, suppliers, customers, and auto-generated emails from the various company productivity systems, like the internal task tracker and discussion forums, the external bug tracking system, and more.

Jamie is a very organized person who likes to designate separate project spaces to track the project activities. His own personal workspace is very organized and project spaces are kept apart. Each customer project is designated a project space to administer the participants, roles, access rights, and maintain provenance for decisions and sources of information. The customers are also included as participants in their respective project spaces. To efficiently coordinate projects, he has a semi-automatic email parsing system to identify customer requests received via email. He implemented an automated project organizer that coordinates activities in a project space for each customer request received via email. The following code snippet in Jamie's automated project organizer sets up a project space and project group members from the email participants list in a customer email.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    public Space getProjectSpace(String projectName) {
        Space projectSpace = findSpaceByName(projectName);
        if (projectSpace == null) {
            Community community = findCommunityByName("Project Management Community");
            Owner owner = session.getActor();
            Date dt = new Date();
            projectSpace = new Space(community, dt);
            projectSpace.setName(projectName);
            projectSpace.setDescription("A space to coordinate a project");
            projectSpace.setOwner(owner);
        }
        return projectSpace;
    }
               
    public Community findCommunityByName(String name) {
        String queryText = "select c from Community c where c.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("name", name);
        Community community = (Community)query.getSingleResult();
        return community;
    }
   
    public Space findSpaceByName(String name) {
        String queryText = "select s from Space s where s.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("name", name);
        Space space = (Space)query.getSingleResult();
        return space;
    }
   
    public Group getProjectGroup(String projectName) {
        String groupName = projectName + "Participants";
        Group group = findGroupByName(projectSpace, groupName);
        if (group == null) {
            Community community = projectSpace.getParent();
            group = findGroupByName(community, groupName);
        }
        if (group == null) {
            Date dt = new Date();
            Owner owner = session.getActor();
            Group participants = new Group(projectSpace, dt);
            participants.setName(groupName);
            participants.setDescription("A group of project participants");
            owner.addAssignedGroup(participants);
        }
        return group;
    }
   
    public Group findGroupByName(Extent extent, String name) {
        String queryText = "select g from Group g where g.parent = :extent and g.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("extent", extent);
        query.setParameter("name", name);
        Group group = (Group)query.getSingleResult();
        return group;
    }
   
    public void addProjectMembers(Group group, UnifiedMessage email) {
        Person self = session.getPerson();
        self.addAssignedGroup(group);
        Participant sender = email.getSender();
        Person client = (Person)sender.getParticipant();
        client.addAssignedGroup(group);
        for (UnifiedMessageParticipant participant : email.getToReceivers()) {
            Addressable addressee = participant.getParticipant();
            if (addressee instanceof Actor) {
                ((Actor)addressee).addAssignedGroup(group);
            }
        }
        for (UnifiedMessageParticipant participant : email.getCcReceivers()) {
            Addressable addressee = participant.getParticipant();
            if (addressee instanceof Actor) {
                ((Actor)addressee).addAssignedGroup(group);
            }
        }
    }

    public void coordinateProject(UnifiedMessage email) {
        instantMessageNotify(email);
        String projectName = "";
        Participant sender = email.getSender();
        Person customer = (Person)sender.getParticipant();
        if (customer != null) {
            projectName += customer.getCompany() + " c/o ";
        }
        projectName += sender.getParticipantName() + " Project";
        projectSpace = getProjectSpace(projectName);
        Group group = getProjectGroup(projectName);
        addProjectMembers(group, email);
        AddressBook addressBook = createProjectContacts(email);
        FreeBusyInterval interval = findFreeInterval(group);
        Calendar calendar = getProjectCalendar(projectName);
        Occurrence meeting = createProjectMeeting(calendar, group, interval, email);
        TaskList taskList = getProjectTaskList(projectName);
        Task task = createProjectTask(taskList, group, interval.getStartDate(), email);
        Conference conference = getProjectConference(projectName);
        setupConference(conference, group, meeting);
        Forum forum = getForum(projectName);
        Discussion discussion = startDiscussionThread(forum, email);
        session.getManager().getTransaction().commit();;
    }

In the following sections, we describe how each ICOM extension module is relevant to this project organizer scenario.

AddressBook Extension Module

The AddressBook extension module defines the entities necessary for the management of contact information about people. The module is very simple from the point of view of number of classes, there are only two, as shown in Figure 1:



Figure 1. The elements of the AddressBook extension module - managing contact information.



Figure 2. Class diagram of PersonContact.

Note: A PersonContact does not represent a person, but rather contact information about a person. Although both are Addressables, PersonContact is a subclass of Artifact, while Person is a subclass of Actor, and belongs in the core model. The two are connected by the bookmark property from PersonContact. This property can take as value an instance of Person.

Usage example

Jamie sets up a project organizer software agent that performs simple actions in response to particular messages in his Inbox,
actions that update a project AddressBook based on the senders and recipients in the messages. If a sender or any one of the recipients of the emails are not already in the project address book, they are automatically added. The following code snippet in the project organizer creates the address book if necessary, queries the contacts by the email addresses, and adds new contacts to the address book if necessary.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    ...

    public AddressBook createProjectContacts(UnifiedMessage email) {
        String projectName = projectSpace.getName();
        AddressBook projectAddressBook = getProjectAddressBook(projectName);
        UnifiedMessageParticipant sender = (UnifiedMessageParticipant) email.getSender();
        addContact(projectAddressBook, sender);      
        for (UnifiedMessageParticipant participant : email.getToReceivers()) {
            addContact(projectAddressBook, participant);
        }
        for (UnifiedMessageParticipant participant : email.getCcReceivers()) {
            addContact(projectAddressBook, participant);
        }
        return projectAddressBook;
    }

    public AddressBook getProjectAddressBook(String projectName) {
        String addressBookName = projectName + "Address Book";
        AddressBook projectAddressBook = findAddressBookByName(projectSpace, addressBookName);
        if (projectAddressBook == null) {
            Date dt = new Date();
            projectAddressBook = new AddressBook(projectSpace, dt, dt);
            projectAddressBook.setName(addressBookName);
        }
        return projectAddressBook;
    }

    public AddressBook findAddressBookByName(Extent extent, String name) {
        String queryText = "select a from AddressBook a where a.parent = :extent and a.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("extent", extent);
        query.setParameter("name", name);
        AddressBook addressBook = (AddressBook)query.getSingleResult();
        return addressBook;
    }

    public PersonContact addContact(AddressBook addressBook,
                                    UnifiedMessageParticipant participant) {
        String name = participant.getDisplayName();
        String emailAddress = participant.getCanonicalAddress();
        EntityAddress address = new EntityAddress();
        try {
            URI uri = new URI(AddressSchemeEnum.MAILTO.name(), emailAddress, (String)null);
            address.setAddress(uri);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
        PersonContact personContact = findContact(addressBook, name, address);
        if (personContact == null) {
            Date dt = new Date();
            personContact = new PersonContact(addressBook, dt, dt);
            personContact.setName(name);
            personContact.setPrimaryAddress(address);
        }
        return personContact;
    }

    public PersonContact findContact(AddressBook addressBook, String name, EntityAddress address) {
        String queryText =
    "select p from PersonContact p where p.parent = :addressBook and
                (p.name = :name or p.primaryAddress = :address or :address member of p.addresses)";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("addressBook", addressBook);
        query.setParameter("name", name);
        query.setParameter("address", address);
        PersonContact personContact = (PersonContact)query.getSingleResult();
        return personContact;
    }

    public void coordinateProject(UnifiedMessage email) {
...
        AddressBook addressBook = createProjectContacts(email);
        ...
        session.getManager().getTransaction().commit();;
    }
}

Presence Extension Module

The Presence extension module defines three principal types, and three respective enumeration types, as shown in Figure 3:



Figure 3. The elements of the Presence extension module.

  • Presence - describes the contact methods and activities of a person.
    It does not belong to any of the three main branches of the core model and is not a subclass of Entity.
  • ContactMethod - describes how a person can be contacted, under given circumstances.
  • Activity - describes what a person is doing.

A presence provides location information, a list of contact methods, and a list of activities describing what a person is doing. The presence information allows clients to choose any one of the contact methods based on circumstances. Only the person who owns the presence is allowed to change it, while everyone else may only have read-only access to it. Such mutability model of presence object is controlled by PresenceEditMode enumeration type.

A contact method provides information about the connection type and status, as well as priority. The possible values for the status are given by the ContactReachabilityStatus enumeration type. At a given time, a Presence can have several or none contact methods available.

A presence instance may be associated with activities. Activities have a start and an end time, and are tied to a reference entity, which can be a task, an event, or a conference. The types of activities are listed by the ActivityType enumeration.

Usage example

Occasionally Jamie receives urgent email requests, about which he wants to be notified immediately, depending on his presence status. The code below shows how his email filter checks his presence and notifies him accordingly.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    ...
   
    public void instantMessageNotify(UnifiedMessage message) {
        Person self = session.getPerson();
        Priority priority = message.getPriority();
        if (priority == PriorityEnum.High) {
            String subject = message.getSubject();
            String sender = message.getSender().getName();

            Presence presence = self.getPresence();
            Collection<Activity> currentActivities = presence.getActivities();
            for (Activity activity : currentActivities) {
                ActivityType activityType = activity.getActivityType();
                if (activityType == ActivityTypeEnum.Meeting) {

                    String imSubject = "High priority message " + subject + " from " + sender;
                    SimpleContent simpleContent = new SimpleContent();
                    OutputStream stream = simpleContent.getOutputStream();
                    try {
                        stream.write(imSubject.getBytes());
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                    simpleContent.setMediaType("text/html");
                    simpleContent.setCharacterEncoding("UTF-8");
                    simpleContent.setContentEncoding("8bit");

                    Participant me = new Participant(self);

                    Date dt = new Date();
                    InstantMessage im = new InstantMessage(null, dt, dt);
                    im.setContent(simpleContent);
                    im.addToReceiver(me);
                    im.setDescription("Urgent email notification");
                   
                    InstantMessageFeed feed = self.getInstantMessageFeed();
                    feed.addOutboundInstantMessages(im);
                }
            }
        }
    }

    public void coordinateProject(UnifiedMessage email) {
        instantMessageNotify(email);
        ...
        session.getManager().getTransaction().commit();;
    }

}

FreeBusy Extension Module

The FreeBusy extension module provides two types for time management. It complements the Calendar extension module described in the next section.

  • FreeBusy - specifies the free and busy intervals of one or more participants. This class contains the list of participants and the list of FreeBusyIntervals.
  • FreeBusyInterval - specifies an interval of time, which can be used for scheduling an event, depending on its availability. The availability of an interval is given by its type.



Figure 4. The elements of the FreeBusy extension module.

Figure 4 shows the relationship between the types and their properties.
The FreeBusyType enumeration defines different possible ways of classifying a time interval.
Values are Free, Busy, Tentative, OutsideAvailableHours, OutOfOffice, and OtherFreeBusyType.

Usage example

Scheduling meetings is a routine task in Jamie’s job. He has several recurring meetings: weekly meetings with his group, bi-weekly meetings with suppliers, and occassional meetings with customers. Most of his meetings are scheduled via email, usually not more than a week in advance.

When a client requests a meeting via email, Jamie schedules the meeting at a time when all colleagues working on the client's project are available. The following code snippet in the project organizer finds a list of possible times for the meeting, by automatically checking the availability of the team members who must attend.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    ...
  
    public FreeBusyInterval findFreeInterval(Group group) {         
        Date start = new Date();
        GregorianCalendar gregorian = new GregorianCalendar();
        gregorian.setTime(start);
        gregorian.add(java.util.Calendar.DAY_OF_MONTH, 5);
        Date end = gregorian.getTime();           
        FreeBusy freeBusy = session.loadFreeBusyOfActors(group.getMemberActors(), start, end);
        FreeBusyInterval free = selectPreferredFreeInterval(freeBusy.getIntervals());
        return free;
    }
   
    FreeBusyInterval selectPreferredFreeInterval(Collection<FreeBusyInterval> intervals) {
        for (FreeBusyInterval interval : intervals) {
            if (interval.getFreeBusyType() == FreeBusyTypeEnum.Free) {
                if (isPreferred(interval.getStartDate(), interval.getEndDate())) {
                    return interval;
                }
            }
        }
        return null;
    }
   
    private boolean isPreferred(Date start, Date end) {
        boolean preferred;
        // evaluate preferences
        return preferred;
    }

    public void coordinateProject(UnifiedMessage email) {
        ...
        FreeBusyInterval interval = findFreeInterval(group);
        Calendar calendar = getProjectCalendar(projectName);
        Occurrence meeting = createProjectMeeting(calendar, group, interval, email);
        ...
        session.getManager().getTransaction().commit();;
    }


}

Calendar Extension Module

The Calendar extension module defines the objects needed to manage events and series of events. There are three principal types, shown in Figure 5, and five enumeration types. The main types are:

  • Calendar - describes a specialized type of folder, which contains time management artifacts, like Occurrences and OccurrenceSeries.
  • Occurrence - represents an event artifact, which is stored in a calendar. It can be standalone, or it can belong to an OccurrenceSeries.
  • OccurrenceSeries - represents a recurring event series.
  • OccurenceParticipant - extends the Participant type defined by the core model, by adding a status property.



Figure 5. The elements of the Calendar extension module.

The enumeration types of the module are:

  • OccurenceStatus - describes the possible states of a calendar occurrence. Possible values are Confirmed, Tentative and Cancelled.
  • OccurenceType - defines possible categories of occurrences belonging to a calendar. Possible values are Meeting, Holiday, DayEvent, JournalEntry and OtherOccurrenceType.
  • OccurenceParticipantStatus - defines the possible responses of a participant to an invitation to a calendar event. Possible values are Accepted, Declined, Tentative, and NeedsAction.
  • OccurrenceParticipantTransparency - defines the possible visibility of an event in a participant's calendar. Possible values are Transparent, Opaque, Tentative, OutOfOffice, and DefaultTransparency.
  • OccurenceEditMode - describes whether an event is editable in a calendar. Possible values are OrganizerCopy (most properties such as location, priority, time are editable by organizer) and AttendeeCopy (only attendee related properties can be edited by attendee).

A calendar stores information regarding its time zone and the set of occurrences and recurrences (occurrence series) that belong to it. Each element in the calendar can be a one-off event, or it can belong to an occurrence series. The enumerations types described above can characterize both one-off events and recurrent ones. Other properties include location, priority, and a list of participants, each with their corresponding answer to the event invitation (status). The occurrence or occurrence series created by the organizer in the organizer's calendar or in a project calendar are organizer's copies, represented by OccurrenceEditModeEnum.OrganizerCopy. The occurrence invitations delivered by the calendar service provider to the attendee's calendar are attendee's copies, represented by OccurrenceEditModeEnum.AttendeeCopy. The organizer can update most of properties such as location, priority, time through the organizer copy. The attendee can update the occurrence participant status and participant priority through the attendee copy. The calendar service provider propagates the updates to the organizer's copy and attendees' copies to all copies of the same occurrence so that they are all in sync. An overview can be seen in Figure 6.



Figure 6. Properties of Occurrence and OccurrenceSeries in the Calendar extension module.

Usage example

Continuing the previous scenario where Jamie needs to schedule a meeting with the customer and team members in the project group, when the free time for the meeting is selected, the following code snippet in the project organizer automatically schedules a meeting in the project calendar. The system will deliver meeting invitations for each of the participants into the participants personal calendars. Each of these invitations are the attendee copies of the occurrence that are synchronized with the organizer copy of the occurrence in the team calendar.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

   ...

    public Calendar getProjectCalendar(String projectName) {
        String calendarName = projectName + "Calendar";
        Calendar calendar = findCalendarByName(projectSpace, calendarName);
        if (calendar == null) {
            Date dt = new Date();
            calendar = new Calendar(projectSpace, dt, dt);
            calendar.setName(calendarName);
        }
        return calendar;
    }

    public Calendar findCalendarByName(Extent extent, String name) {
        String queryText = "select cal from Calendar cal where cal.parent = :extent and cal.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("extent", extent);
        query.setParameter("name", name);
        Calendar calendar = (Calendar)query.getSingleResult();
        return calendar;
    }

    public Occurrence createProjectMeeting(Calendar calendar, Group group, FreeBusyInterval free, UnifiedMessage email) {
        Date dt = new Date();
        Occurrence meeting = new Occurrence(calendar, dt, dt);
        meeting.setName("Client Meeting");
        meeting.setStartDate(free.getStartDate());
        meeting.setEndDate(free.getEndDate());
        meeting.setOccurrenceType(OccurrenceTypeEnum.Meeting);
        meeting.setOccurrenceStatus(OccurrenceStatusEnum.Tentative);
        meeting.setPriority(PriorityEnum.Normal);
        AttachedItem attachment = new AttachedItem(email.getContent().clone());
        meeting.addAttachment(attachment);

        for (Actor actor : group.getMemberActors()) {
            Participant attendee = new Participant(actor);
            meeting.setAttendee(attendee);
        }
        return meeting;
    }

    public void coordinateProject(UnifiedMessage email) {
        ...
        FreeBusyInterval interval = findFreeInterval(group);
        Calendar calendar = getProjectCalendar(projectName);
        Occurrence meeting = createProjectMeeting(calendar, group, interval, email);
        ...
        session.getManager().getTransaction().commit();;
    }

}

TaskList Extension Module

The TaskList extension module handles the management of tasks.
The module defines only two types, as seen in Figure 7.



Figure 7. The elements of the TaskList extension module.

  • Task - defines the subtype of Artifact which is used for task management. It stores all the properties needed to describe a task to do or a task assignment, as shown in Figure 8.
  • TaskList - is a specialization of the Folder class, which can only contain artifacts of type Task.



Figure 8. The Task class, and enumerations.

The extension model also defines enumerations which provide possible values for properties of tasks. An overview is shown in Figure 8.

  • TaskStatus - defines states a Task can be in. Values include InProgress, Completed, NeedsAction, and Cancelled.
  • TaskParticipantStatus - defines possible responses from the participant who was assigned a task. The participant status
    property refers to one assignee of the task. Possible values are Accepted, Declined, InProgress, Completed, WaitingOnOther,
    Tentative, NeedsAction, and Deferred.
  • TaskEditMode - defines which part of the task can be edited by the organizer and the assignee. For example, the organizer can update the task status through the organizer copy. The assignee can update the
    assignee status through assignee copy.

The task created by the organizer in the organizer's task list or in a project task list are organizer's copies, represented by TaskEditMode.OrganizerCopy. The task assignment delivered by the task service provider to the assignee's task list are assignee's copies, represented by TaskEditMode.AssigneeCopy. The organizer can update most of properties such as priority, start date, due date through the organizer copy. The assignee can update the task participant status through the assignee copy. The task service provider propagates the updates to the organizer's copy and assignee' copies to all copies of the same task so that they are all in sync.

Usage example

Continuing on the meeting scheduling example, after creating the meeting with the customer and team members, the automatic project organizer creates a task in the project task list to review the meeting agenda and to prepare the proposals, presentations, or discussions in the meeting. A task assignment will be delivered for each participant into the participant's personal task list. Each of these task assignments are the assignee copies of the task that are synchronized with the organizer copy of the task in the team task list.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    ...

    public TaskList getProjectTaskList(String projectName) {
        String taskListName = projectName + "TaskList";
        TaskList taskList = findTaskListByName(projectSpace, taskListName);
        if (taskList == null) {
            Date dt = new Date();
            taskList = new TaskList(projectSpace, dt, dt);
            taskList.setName(taskListName);
        }
        return taskList;
    }

    public TaskList findTaskListByName(Extent extent, String name) {
        String queryText = "select t from TaskList t where t.parent = :extent and t.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("extent", extent);
        query.setParameter("name", name);
        TaskList taskList = (TaskList)query.getSingleResult();
        return taskList;
    }

    public Task createProjectTask(TaskList taskList, Group group, Date due,
                                  UnifiedMessage email) {
        Date dt = new Date();
        Task task = new Task(taskList, dt, dt);
        task.setName("Define agenda for meeting");
        task.setDescription("Task asisignments to each of " + group.getName() +
                            " to review the agenda for the meeting");
        task.setStartDate(dt);
        task.setDueDate(due);
        task.setAssignee(new Participant(group));
        AttachedItem attachment = new AttachedItem(email.getContent().clone());
        task.addAttachment(attachment);
        task.setPriority(PriorityEnum.Normal);
        task.setTaskStatus(TaskStatusEnum.InProgress);
        task.setPercentComplete(0);
        return task;
    }

    public void coordinateProject(UnifiedMessage email) {
        ...
        TaskList taskList = getProjectTaskList(projectName);
        Task task = createProjectTask(taskList, group, interval.getStartDate(), email);
        ...
        session.getManager().getTransaction().commit();;
    }

  
}

Conference Extension Module

The Conference extension module provides the web, voice, video conferencing capability. The information model defined in the module are shown in Figure 9. The main classes are detailed here:

  • Conference - represents a durable context for conference sessions. It stores all the information necessary for a conference,
    including organizer, type, participants and roles settings, current session, scheduled times, and transcripts.
  • ConferenceSession - represents a session of a conference. Multiple sessions of a recurring conference call are represented by separate
    ConferenceSession objects which belong to the same Conference object.
  • ConferenceSetting - contains information about the participants, roles, keys, and other settings of a conference.
  • ConferenceParticipantRole - defines the role of one or more participants in the conference sessions, including access keys and keywords.



Figure 9. The elements of the Conference extension module.

Additionally, the module defines three enumeration types, which store possible values for:

  • ConferenceType - describing the conference type, which can be one of: Impromptu, Scheduled, ChatRoom, and other.
  • ConferenceStatus - describes current status of an online conference: NotStarted, WaitingForHost, Running, Hibernating, Ended.
  • ConferenceSessionEndingReason - defines possible reasons for a conference call ending: HostLeft, HostAborted, NoHost,Hibernating.

Usage example

Jamie has a recurring meeting with his team about this customer project, for which they use the same conference in the project space so
that transcripts of all conference sessions can be archived in this conference. Conference represents a folder of transcripts as well as a durable metadata object to propagate the project contexts and settings to the transient runtime sessions. The following code snippet in the automatic project organizer sets up the conference and schedule it with the meeting in the team calendar. The conference settings are configured with the team members as participants. The conference is associated with the meeting in the team calendar. The meeting reminder will include the conference URL, through which Jamie and all meeting attendees can resume or rejoin the conference session at the scheduled time.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    ...

    public Conference getProjectConference(String projectName) {
        String conferenceName = projectName + "Conference";
        Conference conference = findConferenceByName(projectSpace, conferenceName);
        if (conference == null) {
            Date dt = new Date();
            conference = new Conference(projectSpace, dt, dt);
            conference.setName(conferenceName);
            conference.setDescription("Project conference");
            conference.setConferenceType(ConferenceTypeEnum.Scheduled);
        }
        return conference;
    }

    public Conference findConferenceByName(Extent extent, String name) {
        String queryText = "select conf from Conference conf where conf.parent = :extent and conf.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("extent", extent);
        query.setParameter("name", name);
        Conference conference = (Conference)query.getSingleResult();
        return conference;
    }
   
    public void setupConference(Conference conference, Group group,
                                Occurrence meeting) {
        conference.setOwner(group);
        ConferenceSetting setting = new ConferenceSetting();
        ConferenceParticipantRole role = new ConferenceParticipantRole();
        role.addParticipant(new Participant(group));
        role.setName("All project participants");
        setting.addParticipantRole(role);
        conference.setConferenceSetting(setting);
        meeting.addConference(conference);
    }

    public void coordinateProject(UnifiedMessage email) {
        ...
        Conference conference = getProjectConference(projectName);
        setupConference(conference, group, meeting);
        ...
        session.getManager().getTransaction().commit();;
    }


}

Forum Extension Module

The Forum extension module follows the previous model of providing specialized classes for containers and artifacts. As shown in Figure 10 and described below, the classes of this module can be on one of three levels of containment:

  • DiscussionMessage - defines a specialised type of artifact which represents a discussion message.
  • Topic - defines a specialised folder for discussions which can be sorted chronologically, or threaded.
  • Announcement - defines a specialised artifact which is a time-sensitive topic that is valid for a given period of time.
  • Forum - defines a specialised folder which contains topics, sub-forums and announcements.



Figure 10. The elements of the Forum extension module.

The module also defines three interfaces. Discussion stores the characteristics of an item of a discussion container. The DiscussionMessage implements this interface, and thus can be used as an item in a DiscussionContainer. DiscussionContainer defines a specialised type of container which can hold discussion items. The Topic class implements this interface. TopicContainer defines a specialised container for topics. The Forum class implements this interface.

This module defines a single enumeration type, the AnnouncementStatus, which defines possible values for the status of an announcement: Pending, Active, Expired.

Usage example

The email message from the customer contains a specification of the product that Jamie's factory will fabricate. The following code snippet in the automatic project organizer posts the email message content to the forum in the project space. Thus the product specification and earlier email threads between Jamie and the customer would now be accessible to any new participants of the project. Any ensuing discussions about the product specification can continue more openly in the project forum.

public class ProjectOrganizer {
   
    Session session;
   
    Space projectSpace;

    ...
  
    public Forum getForum(String projectName) {
        String forumName = projectName + "Forum";
        Forum forum = findForumByName(projectSpace, forumName);
        if (forum == null) {
            Date dt = new Date();
            forum = new Forum(projectSpace, dt, dt);
            forum.setName(forumName);
            forum.setDescription("Project forum");
        }
        return forum;
    }

    public Forum findForumByName(Extent extent, String name) {
        String queryText = "select f from Forum f where f.parent = :extent and f.name = :name";
        EntityManager manager = session.getManager();
        Query query = manager.createQuery(queryText);
        query.setParameter("extent", extent);
        query.setParameter("name", name);
        Forum forum = (Forum)query.getSingleResult();
        return forum;
    }
   
    public Discussion startDiscussionThread(Forum forum, UnifiedMessage email) {
        Date dt = new Date();
        Topic topic = new Topic(forum, dt, dt);
        DiscussionMessage discussion = new DiscussionMessage(topic, dt, dt);
        discussion.setName(email.getSubject());
        discussion.setContent(email.getContent().clone());
        return discussion;
    }

    public void coordinateProject(UnifiedMessage email) {
        ...
        Forum forum = getForum(projectName);
        Discussion discussion = startDiscussionThread(forum, email);
        session.getManager().getTransaction().commit();;
    }
  
}

Conclusion

This article is the second part of the multi-part series introducing the java.net incubation project for JPA ICOM framework. It describes the extension modules of the ICOM model and shows usage examples. Part 3 will describe the design and implementation of a Semantic Media Wiki extension using ICOM.

While the core model defines the general framework and concepts, the extension models are responsible for concrete collaboration services, like email, calendar and task management. We covered the AddressBook, Presence, Calendar, FreeBusy, Task, Conference, and Forum extension modules.

Resources and references

Acknowledgements

The authors wish to extend their thanks to their colleagues, especially the developers of the Oracle Beehive Collaboration Services, who have helped with their domain expertise. Especially, we thank Rafiul Ahad, Stefan Decker, Deirdre Lee, the ICOM TC members, and the OASIS staff for supporting the work on the ICOM Committee Specification 01.

Related Topics >> Featured Article   |