Java tutorial
/* * Copyright (C) 2016 Keith M. Hughes * Copyright (C) 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package io.smartspaces.master.server.services.internal.support; import io.smartspaces.SmartSpacesException; import io.smartspaces.domain.basic.Activity; import io.smartspaces.domain.basic.ActivityConfiguration; import io.smartspaces.domain.basic.ActivityDependency; import io.smartspaces.domain.basic.ConfigurationParameter; import io.smartspaces.domain.basic.LiveActivityGroupLiveActivity; import io.smartspaces.domain.basic.LiveActivity; import io.smartspaces.domain.basic.LiveActivityGroup; import io.smartspaces.domain.basic.Resource; import io.smartspaces.domain.basic.Space; import io.smartspaces.domain.basic.SpaceController; import io.smartspaces.domain.basic.SpaceControllerConfiguration; import io.smartspaces.domain.basic.SpaceControllerMode; import io.smartspaces.domain.system.NamedScript; import io.smartspaces.master.server.services.ActivityRepository; import io.smartspaces.master.server.services.AutomationRepository; import io.smartspaces.master.server.services.ResourceRepository; import io.smartspaces.master.server.services.SpaceControllerRepository; import org.jdom2.CDATA; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.output.Format; import org.jdom2.output.XMLOutputter; import java.io.IOException; import java.io.StringWriter; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * A creator of the master domain description which uses JDOM. * * @author Keith M. Hughes */ public class JdomMasterDomainModelCreator implements MasterDomainDescription { /** * Create a description of the entire space domain. * * @param activityRepository * the repository for activity entities * @param controllerRepository * the repository for controller entities * @param resourceRepository * the repository for resources * @param automationRepository * the repository for automation entities * * @return the XML description */ public String newModel(ActivityRepository activityRepository, SpaceControllerRepository controllerRepository, ResourceRepository resourceRepository, AutomationRepository automationRepository) { try { Element rootElement = new Element(ELEMENT_NAME_DESCRIPTION_ROOT_ELEMENT); Document document = new Document(rootElement); rootElement.addContent(newSpaceControllerEntries(controllerRepository)); rootElement.addContent(newActivityEntries(activityRepository)); rootElement.addContent(newLiveActivityEntries(activityRepository)); rootElement.addContent(newLiveActivityGroupEntries(activityRepository)); rootElement.addContent(newSpaceEntries(activityRepository)); rootElement.addContent(newResourceEntries(resourceRepository)); rootElement.addContent(newNamedScriptEntries(automationRepository)); StringWriter out = new StringWriter(); Format format = Format.getPrettyFormat(); XMLOutputter outputter = new XMLOutputter(format); outputter.output(document, out); return out.toString(); } catch (IOException e) { throw new SmartSpacesException("Could not create domain model", e); } } /** * Create the space controllers section. * * @param controllerRepository * repository for the controllers * * @return the element for all controllers */ private Element newSpaceControllerEntries(SpaceControllerRepository controllerRepository) { Element controllersElement = new Element(ELEMENT_NAME_ROOT_SPACE_CONTROLLERS); for (SpaceController controller : controllerRepository.getAllSpaceControllers()) { controllersElement.addContent(newSpaceControllerEntry(controller)); } return controllersElement; } /** * Create the entry for a specific space controller. * * @param controller * the controller to write * * @return the element for the controller */ private Element newSpaceControllerEntry(SpaceController controller) { Element controllerElement = new Element(ELEMENT_NAME_INDIVIDUAL_SPACE_CONTROLLER); controllerElement.setAttribute(ATTRIBUTE_NAME_ID, controller.getId()) .addContent(new Element(ELEMENT_NAME_NAME).addContent(controller.getName())) .addContent( new Element(ELEMENT_NAME_DESCRIPTION).addContent(new CDATA(controller.getDescription()))) .addContent(new Element(ELEMENT_NAME_SPACE_CONTROLLER_HOST_ID).addContent(controller.getHostId())) .addContent( new Element(ELEMENT_NAME_SPACE_CONTROLLER_HOST_NAME).addContent(controller.getHostName())) .addContent(new Element(ELEMENT_NAME_SPACE_CONTROLLER_HOST_CONTROL_PORT) .addContent(Integer.toString(controller.getHostControlPort()))) .addContent(new Element(ELEMENT_NAME_UUID).addContent(controller.getUuid())) .addContent(newMetadataElement(controller.getMetadata())); SpaceControllerMode mode = controller.getMode(); if (mode != null) { controllerElement.addContent(new Element(ELEMENT_NAME_SPACE_CONTROLLER_MODE).addContent(mode.name())); } addSpaceControllerConfiguration(controllerElement, controller.getConfiguration()); return controllerElement; } /** * Add a space controller configuration to the given element if there is a * configuration. * * @param element * the XML element to add the configuration onto * @param configuration * the possible configuration (can be {@code null}) */ private void addSpaceControllerConfiguration(Element element, SpaceControllerConfiguration configuration) { if (configuration != null) { Element configurationElement = new Element(ELEMENT_NAME_SPACE_CONTROLLER_CONFIGURATION); element.addContent(configurationElement); Set<ConfigurationParameter> parameters = configuration.getParameters(); if (!parameters.isEmpty()) { Element parametersElement = new Element( ELEMENT_NAME_SPACE_CONTROLLER_CONFIGURATION_ROOT_PARAMETERS); configurationElement.addContent(parametersElement); for (ConfigurationParameter parameter : parameters) { Element parameterElement = new Element( ELEMENT_NAME_SPACE_CONTROLLER_CONFIGURATION_INDIVIDUAL_PARAMETER); parametersElement.addContent(parameterElement); parameterElement.setAttribute(ATTRIBUTE_NAME_SPACE_CONTROLLER_CONFIGURATION_PARAMETER_NAME, parameter.getName()).addContent(new CDATA(parameter.getValue())); } } } } /** * Create the activities section. * * @param activityRepository * repository for the activities * * @return the element for all activities */ private Element newActivityEntries(ActivityRepository activityRepository) { Element activitiesElement = new Element(ELEMENT_NAME_ROOT_ACTIVITIES); for (Activity activity : activityRepository.getAllActivities()) { activitiesElement.addContent(newActivityEntry(activity)); } return activitiesElement; } /** * Create the entry for a specific activity. * * @param activity * the activity to write * * @return the element for the activity */ private Element newActivityEntry(Activity activity) { Element activityElement = new Element(ELEMENT_NAME_INDIVIDUAL_ACTIVITY); activityElement.setAttribute(ATTRIBUTE_NAME_ID, activity.getId()) .addContent(new Element(ELEMENT_NAME_ACTIVITY_IDENTIFYING_NAME) .addContent(activity.getIdentifyingName())) .addContent(new Element(ELEMENT_NAME_ACTIVITY_VERSION).addContent(activity.getVersion())) .addContent(new Element(ELEMENT_NAME_NAME).addContent(activity.getName())) .addContent(new Element(ELEMENT_NAME_DESCRIPTION).addContent(new CDATA(activity.getDescription()))) .addContent(newMetadataElement(activity.getMetadata())); Date lastUploadDate = activity.getLastUploadDate(); if (lastUploadDate != null) { activityElement.setAttribute(ATTRIBUTE_NAME_LAST_UPLOAD_DATE, Long.toString(lastUploadDate.getTime())); } Date lastStartDate = activity.getLastStartDate(); if (lastStartDate != null) { activityElement.setAttribute(ATTRIBUTE_NAME_LAST_START_DATE, Long.toString(lastStartDate.getTime())); } String bundleContentHash = activity.getBundleContentHash(); if (bundleContentHash != null) { activityElement.addContent( new Element(ELEMENT_NAME_ACTIVITY_BUNDLE_CONTENT_HASH).addContent(bundleContentHash)); } addActivityDependencies(activity, activityElement); return activityElement; } /** * Add the dependencies for an activity, if any. * * @param activity * the activity with the dependencies * @param activityElement * the XML element to hang the dependencies off of */ protected void addActivityDependencies(Activity activity, Element activityElement) { List<? extends ActivityDependency> dependencies = activity.getDependencies(); if (!dependencies.isEmpty()) { Element activityDependenciesElement = new Element(ELEMENT_NAME_ROOT_ACTIVITY_DEPENDENCIES); activityElement.addContent(activityDependenciesElement); for (ActivityDependency dependency : dependencies) { Element dependencyElement = new Element(ELEMENT_NAME_INDIVIDUAL_ACTIVITY_DEPENDENCY); activityDependenciesElement.addContent(dependencyElement); dependencyElement .addContent(new Element(ELEMENT_NAME_ACTIVITY_DEPENDENCY_NAME) .addContent(dependency.getIdentifyingName())) .addContent(new Element(ELEMENT_NAME_ACTIVITY_DEPENDENCY_VERSION_MINIMUM) .addContent(dependency.getMinimumVersion())) .addContent(new Element(ELEMENT_NAME_ACTIVITY_DEPENDENCY_VERSION_MAXIMUM) .addContent(dependency.getMaximumVersion())) .addContent(new Element(ELEMENT_NAME_ACTIVITY_DEPENDENCY_REQUIRED) .addContent(dependency.isRequired() ? VALUE_TRUE : VALUE_FALSE)); } } } /** * Create the live activities section. * * @param activityRepository * repository for the activity entities * * @return the element for all live activities */ private Element newLiveActivityEntries(ActivityRepository activityRepository) { Element activitiesElement = new Element(ELEMENT_NAME_ROOT_LIVE_ACTIVITIES); for (LiveActivity activity : activityRepository.getAllLiveActivities()) { activitiesElement.addContent(newLiveActivityEntry(activity)); } return activitiesElement; } /** * Create the entry for a specific live activity. * * @param liveActivity * the live activity to write * * @return the element for the activity */ private Element newLiveActivityEntry(LiveActivity liveActivity) { Element liveActivityElement = new Element(ELEMENT_NAME_INDIVIDUAL_LIVE_ACTIVITY); liveActivityElement.setAttribute(ATTRIBUTE_NAME_ID, liveActivity.getId()) .addContent(new Element(ELEMENT_NAME_UUID).addContent(liveActivity.getUuid())) .addContent(new Element(ELEMENT_NAME_NAME).addContent(liveActivity.getName())) .addContent( new Element(ELEMENT_NAME_DESCRIPTION).addContent(new CDATA(liveActivity.getDescription()))) .addContent(new Element(ELEMENT_NAME_LIVE_ACTIVITY_CONTROLLER).setAttribute(ATTRIBUTE_NAME_ID, liveActivity.getController().getId())) .addContent(new Element(ELEMENT_NAME_LIVE_ACTIVITY_ACTIVITY).setAttribute(ATTRIBUTE_NAME_ID, liveActivity.getActivity().getId())) .addContent(newMetadataElement(liveActivity.getMetadata())); addActivityConfiguration(liveActivityElement, liveActivity.getConfiguration()); Date lastDeployDate = liveActivity.getLastDeployDate(); if (lastDeployDate != null) { liveActivityElement.addContent(new Element(ELEMENT_NAME_LIVE_ACTIVITY_LAST_DEPLOY_DATE) .addContent(Long.toString(lastDeployDate.getTime()))); } return liveActivityElement; } /** * Add an activity configuration to the given element if there is a * configuration. * * @param element * the XML element to add the configuration onto * @param configuration * the possible configuration (can be {@code null}) */ private void addActivityConfiguration(Element element, ActivityConfiguration configuration) { if (configuration != null) { Element configurationElement = new Element(ELEMENT_NAME_ACTIVITY_CONFIGURATION); element.addContent(configurationElement); Set<ConfigurationParameter> parameters = configuration.getParameters(); if (!parameters.isEmpty()) { Element parametersElement = new Element(ELEMENT_NAME_ACTIVITY_CONFIGURATION_ROOT_PARAMETERS); configurationElement.addContent(parametersElement); for (ConfigurationParameter parameter : parameters) { Element parameterElement = new Element( ELEMENT_NAME_ACTIVITY_CONFIGURATION_INDIVIDUAL_PARAMETER); parametersElement.addContent(parameterElement); parameterElement .setAttribute(ATTRIBUTE_NAME_ACTIVITY_CONFIGURATION_PARAMETER_NAME, parameter.getName()) .addContent(new CDATA(parameter.getValue())); } } } } /** * Create the live activity groups section. * * @param activityRepository * repository for the activity entities * * @return the element for all live activity groups */ private Element newLiveActivityGroupEntries(ActivityRepository activityRepository) { Element groupsElement = new Element(ELEMENT_NAME_ROOT_LIVE_ACTIVITY_GROUPS); for (LiveActivityGroup group : activityRepository.getAllLiveActivityGroups()) { groupsElement.addContent(newLiveActivityGroupEntry(group)); } return groupsElement; } /** * Create the entry for a specific live activity group. * * @param group * the live activity group to write * * @return the element for the live activity group */ private Element newLiveActivityGroupEntry(LiveActivityGroup group) { Element groupElement = new Element(ELEMENT_NAME_INDIVIDUAL_LIVE_ACTIVITY_GROUP); groupElement.setAttribute(ATTRIBUTE_NAME_ID, group.getId()) .addContent(new Element(ELEMENT_NAME_NAME).addContent(new CDATA(group.getName()))) .addContent(new Element(ELEMENT_NAME_DESCRIPTION).addContent(new CDATA(group.getDescription()))) .addContent(newMetadataElement(group.getMetadata())); addLiveActivityGroupLiveActivities(group, groupElement); return groupElement; } /** * Add any live activities in the group. * * @param group * the group which should have activities * @param groupElement * the XML element for the group */ private void addLiveActivityGroupLiveActivities(LiveActivityGroup group, Element groupElement) { List<? extends LiveActivityGroupLiveActivity> activities = group.getLiveActivities(); if (!activities.isEmpty()) { Element activitiesElement = new Element(ELEMENT_NAME_LIVE_ACTIVITY_GROUP_ROOT_GROUP_LIVE_ACTIVITIES); groupElement.addContent(activitiesElement); for (LiveActivityGroupLiveActivity activity : activities) { Element activityElement = new Element( ELEMENT_NAME_LIVE_ACTIVITY_GROUP_INDIVIDUAL_GROUP_LIVE_ACTIVITY); activitiesElement.addContent(activityElement); activityElement .setAttribute(ATTRIBUTE_NAME_GROUP_LIVE_ACTIVITY_ID, activity.getLiveActivity().getId()) .setAttribute(ATTRIBUTE_NAME_GROUP_LIVE_ACTIVITY_DEPENDENCY, activity.getDependencyType().name()); } } } /** * Create the spaces section. * * @param activityRepository * repository for the space entities * * @return the element for all spaces */ private Element newSpaceEntries(ActivityRepository activityRepository) { Element spacesElement = new Element(ELEMENT_NAME_ROOT_SPACES); Set<String> spacesDone = new HashSet<>(); for (Space rootSpace : activityRepository.getAllSpaces()) { walkSpace(spacesElement, spacesDone, rootSpace); } return spacesElement; } /** * Do a depth first walk of space so get everything that needs to be defined * written out before it is used. * * @param spacesElement * element where spaces get attached * @param spacesDone * IDs of the spaces which have been done * @param space * the current space */ private void walkSpace(Element spacesElement, Set<String> spacesDone, Space space) { if (!spacesDone.contains(space.getId())) { // Though there better not be circularly defined spaces, this will // help not get trapped by them. spacesDone.add(space.getId()); for (Space subspace : space.getSpaces()) { walkSpace(spacesElement, spacesDone, subspace); } spacesElement.addContent(newSpaceEntry(space)); } } /** * Create the entry for a specific space. * * @param space * the space to write * * @return the element for the space */ private Element newSpaceEntry(Space space) { Element spaceElement = new Element(ELEMENT_NAME_INDIVIDUAL_SPACE); spaceElement.setAttribute(ATTRIBUTE_NAME_ID, space.getId()) .addContent(new Element(ELEMENT_NAME_NAME).addContent(new CDATA(space.getName()))) .addContent(new Element(ELEMENT_NAME_DESCRIPTION).addContent(new CDATA(space.getDescription()))) .addContent(newMetadataElement(space.getMetadata())); addSubspaces(space, spaceElement); addSpaceLiveActivityGroups(space, spaceElement); return spaceElement; } /** * Add any subspace elements needed. * * @param space * the space which contains the subspaces * @param spaceElement * the space element where the entries should be added */ private void addSubspaces(Space space, Element spaceElement) { List<? extends Space> subspaces = space.getSpaces(); if (!subspaces.isEmpty()) { Element subspacesElement = new Element(ELEMENT_NAME_SPACE_ROOT_SUBSPACES); spaceElement.addContent(subspacesElement); for (Space subspace : subspaces) { subspacesElement.addContent(new Element(ELEMENT_NAME_SPACE_INDIVIDUAL_SUBSPACE) .setAttribute(ATTRIBUTE_NAME_ID, subspace.getId())); } } } /** * Add any live activity group elements needed from a space. * * @param space * the space which contains the live activity groups * @param spaceElement * the space element where the entries should be added */ private void addSpaceLiveActivityGroups(Space space, Element spaceElement) { List<? extends LiveActivityGroup> groups = space.getActivityGroups(); if (!groups.isEmpty()) { Element groupsElement = new Element(ELEMENT_NAME_SPACE_ROOT_LIVE_ACTIVITY_GROUPS); spaceElement.addContent(groupsElement); for (LiveActivityGroup group : groups) { groupsElement.addContent(new Element(ELEMENT_NAME_SPACE_INDIVIDUAL_LIVE_ACTIVITY_GROUP) .setAttribute(ATTRIBUTE_NAME_ID, group.getId())); } } } /** * Create the resources section. * * @param resourceRepository * repository for the resources * * @return the element for all resources */ private Element newResourceEntries(ResourceRepository resourceRepository) { Element resourcesElement = new Element(ELEMENT_NAME_ROOT_RESOURCES); for (Resource resource : resourceRepository.getAllResources()) { resourcesElement.addContent(newResourceEntry(resource)); } return resourcesElement; } /** * Create the entry for a specific resource. * * @param resource * the resource to write * * @return the element for the resource */ private Element newResourceEntry(Resource resource) { Element resourceElement = new Element(ELEMENT_NAME_INDIVIDUAL_RESOURCE); resourceElement.setAttribute(ATTRIBUTE_NAME_ID, resource.getId()) .addContent(new Element(ELEMENT_NAME_RESOURCE_IDENTIFYING_NAME) .addContent(resource.getIdentifyingName())) .addContent(new Element(ELEMENT_NAME_RESOURCE_VERSION).addContent(resource.getVersion())); Date lastUploadDate = resource.getLastUploadDate(); if (lastUploadDate != null) { resourceElement.setAttribute(ATTRIBUTE_NAME_LAST_UPLOAD_DATE, Long.toString(lastUploadDate.getTime())); } String bundleContentHash = resource.getBundleContentHash(); if (bundleContentHash != null) { resourceElement.addContent( new Element(ELEMENT_NAME_RESOURCE_BUNDLE_CONTENT_HASH).addContent(bundleContentHash)); } return resourceElement; } /** * Create all named script entries. *activity * @param automationRepository * repository which contains the scripts * * @return an XML element for all master scripts */ private Element newNamedScriptEntries(AutomationRepository automationRepository) { Element scriptsElement = new Element(ELEMENT_NAME_ROOT_NAMED_SCRIPTS); for (NamedScript script : automationRepository.getAllNamedScripts()) { scriptsElement.addContent(newNamedScriptEntry(script)); } return scriptsElement; } /** * Create the entry for a specific named script. * * @param script * the named script to write * * @return the XML element for the named script */ private Element newNamedScriptEntry(NamedScript script) { Element scriptElement = new Element(ELEMENT_NAME_INDIVIDUAL_NAMED_SCRIPT); scriptElement.setAttribute(ATTRIBUTE_NAME_ID, script.getId()) .addContent(new Element(ELEMENT_NAME_NAME).addContent(new CDATA(script.getName()))) .addContent(new Element(ELEMENT_NAME_DESCRIPTION).addContent(new CDATA(script.getDescription()))) .addContent(new Element(ELEMENT_NAME_NAMED_SCRIPT_LANGUAGE).addContent(script.getLanguage())) .addContent( new Element(ELEMENT_NAME_NAMED_SCRIPT_CONTENT).addContent(new CDATA(script.getContent()))) .addContent(newMetadataElement(script.getMetadata())); Element scheduleElement = new Element(ELEMENT_NAME_NAMED_SCRIPT_SCHEDULE) .addContent(new CDATA(script.getSchedule())); scheduleElement.setAttribute(ATTRIBUTE_NAME_NAMED_SCRIPT_SCHEDULE_SCHEDULED, script.getScheduled() ? VALUE_TRUE : VALUE_FALSE); scriptElement.addContent(scheduleElement); return scriptElement; } /** * Create a metadata element. * * @param metadata * the metadata to create the XML for * * @return the XML description of the metadata */ private Element newMetadataElement(Map<String, Object> metadata) { Element metadataElement = new Element(ELEMENT_NAME_METADATA); for (Entry<String, Object> entry : metadata.entrySet()) { metadataElement.addContent(new Element(ELEMENT_NAME_METADATA_ITEM) .setAttribute(ATTRIBUTE_NAME_METADATA_ITEM_NAME, entry.getKey()) .addContent(new CDATA(entry.getValue().toString()))); } return metadataElement; } }