/** * Copyright 2008-2016 Qualogy Solutions B.V. * * 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 com.qualogy.qafe.bind.domain; /** * $Rev:: $: Revision of last commit $Author:: $: Author of last commit $Date:: $: Date of last commit */ import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.logging.Logger; import org.jibx.runtime.IUnmarshallingContext; import com.qualogy.qafe.bind.PostProcessing; import com.qualogy.qafe.bind.ValidationException; import com.qualogy.qafe.bind.commons.type.Reference; import com.qualogy.qafe.bind.core.statement.ControlStatement; import com.qualogy.qafe.bind.core.statement.IfResult; import com.qualogy.qafe.bind.core.statement.IfStatement; import com.qualogy.qafe.bind.core.statement.Iteration; import com.qualogy.qafe.bind.core.statement.ResultItem; import com.qualogy.qafe.bind.core.statement.SwitchResult; import com.qualogy.qafe.bind.core.statement.SwitchResults; import com.qualogy.qafe.bind.core.statement.SwitchStatement; import com.qualogy.qafe.bind.item.Item; import com.qualogy.qafe.bind.presentation.component.View; import com.qualogy.qafe.bind.presentation.component.Window; import com.qualogy.qafe.bind.presentation.event.Event; import com.qualogy.qafe.bind.presentation.event.InputVariable; import com.qualogy.qafe.bind.presentation.event.function.EventRef; import com.qualogy.qafe.bind.presentation.style.Style; import com.qualogy.qafe.bind.presentation.style.StyleSet; public class PresentationTier implements Serializable, PostProcessing, Tier { private static final long serialVersionUID = 8021402983709812487L; protected List<Event> events; protected StyleSet styles; protected View view; protected Map<String, Event> eventsMap = new HashMap<String, Event>(17); public PresentationTier(List<Event> events, StyleSet styles, View screens) { this.events = events; this.styles = styles; this.view = screens; } public PresentationTier() { } public static PresentationTier create(List<Event> events, StyleSet styles, View screens) { return new PresentationTier(events, styles, screens); } /** * @return the events */ public List<Event> getEvents() { return events; } /** * * @param events * the events to set */ public void setEvents(List<Event> events) { this.events = events; } /** * @return the styles */ public StyleSet getStyles() { return styles; } public void validate() throws ValidationException { } /** * method to add a Event to a Event list. The list will be created when null * * @param action * @throws IllegalArgumentException - when object param passed is null */ public void add(Event event) { if (event == null) { throw new IllegalArgumentException("Event cannot be null"); } if (events == null) { events = new ArrayList<Event>(); } events.add(event); } /** * method to add a Style to a Style list. The list will be created when null * * @param action * @throws IllegalArgumentException - when object param passed is null */ public void add(Style style) { if (style == null) { throw new IllegalArgumentException("Style cannot be null"); } if (styles == null) { styles = new StyleSet(); } styles.add(style); } public void postset(IUnmarshallingContext context) { performPostProcessing(); } public void performPostProcessing() { // Since events can be referenced from other events, the map for // convenience is set up after processing. if (events != null) { for (Event event : events) { if (eventsMap.containsKey(event.getId())) { String errorMessage = "Event with id '" + event.getId() + "' is defined more than once in the global events. " + "Id of an event should be unqiue within the global events. Please correct this problem"; Logger.getLogger(this.getClass().getName()).severe(errorMessage); throw new ValidationException(errorMessage); } eventsMap.put(event.getId(), event); } } Logger.getLogger(this.getClass().getName()).info("" + eventsMap.size() + " global events found"); // Id of a global event should be unique within the application context checkIfEventsExistInWindows(); // Populate the inputVariables when events are referenced. // All the post-set methods on events are executed. if (getView() != null) { if (getView().getWindows() != null) { for (Window window : getView().getWindows()) { processEvents(window); } } } processEvents(getEvents(), null); } private void checkIfEventsExistInWindows() { if ((getView() != null) && (getView().getWindows() != null)) { List<Window> windowList = getView().getWindows(); for (Window window : windowList) { if (window.getEvents() != null) { for (Event event : window.getEvents()) { if (eventsMap.containsKey(event.getId())) { String errorMessage = "Event with id '" + event.getId() + "' is defined in the local events for window [" + window.getId() + "] which also exists within the global events. Please correct this problem"; Logger.getLogger(this.getClass().getName()).severe(errorMessage); throw new ValidationException(errorMessage); } } } } } } private void processEvents(Window w) { if (w == null) { return; } processEvents(w.getEvents(), w); } private void processEvents(List<Event> events, Window w) { if (events == null) { return; } for (Event event : events) { processEvent(event, w); } } // CHECKSTYLE.OFF: CyclomaticComplexity private void processEvent(Event event, Window w) { if ((event == null) || (event.getEventItems() == null)) { return; } Set<String> processedEvents = new HashSet<String>(); Queue<Item> queue = new LinkedList<Item>(); for (Item eventItem : event.getEventItems()) { queue.offer(eventItem); } while (!queue.isEmpty()) { Item eventItem = queue.poll(); if (eventItem instanceof EventRef) { EventRef eventRef = (EventRef)eventItem; String subEventId = eventRef.getEvent(); if (processedEvents.contains(subEventId)) { continue; } processedEvents.add(subEventId); //TODO: As a Qafe Developer I want to find recursive events in application loading so that I will get warning about potential issue in the code. Event subEvent = getEventById(subEventId, w); if (subEvent == null) { continue; } if (subEvent.getInput() != null) { event.addAllParameters(subEvent.getInput()); } if (subEvent.getEventItems() != null) { for (Item subEventItem : subEvent.getEventItems()) { queue.offer(subEventItem); } } } else if (eventItem instanceof ControlStatement) { ControlStatement controlStatement = (ControlStatement)eventItem; List<Item> resultItems = getResultItems(controlStatement); if (resultItems != null) { for (Item resultItem : resultItems) { queue.offer(resultItem); } } if (controlStatement instanceof Iteration) { Iteration iteration = (Iteration)controlStatement; Reference reference = iteration.getReference(); if ((reference != null) && reference.isComponentReference()) { InputVariable inputVariable = new InputVariable(reference.stringValueOf(), reference.stringValueOf(), null); List<InputVariable> inputVariables = new ArrayList<InputVariable>(); inputVariables.add(inputVariable); event.addAllParameters(inputVariables); } } } } } // CHECKSTYLE.ON: CyclomaticComplexity private Event getEventById(String eventId, Window w) { Event event = null; Map<String,Event> eventsMap = null; if (w != null) { eventsMap = w.getEventsMap(); if (eventsMap != null) { event = eventsMap.get(eventId); } } if (event == null) { eventsMap = getEventsMap(); if (eventsMap != null) { event = eventsMap.get(eventId); } } return event; } private List<Item> getResultItems(ControlStatement controlStatement) { List<Item> resultItems = new ArrayList<Item>(); if (controlStatement instanceof Iteration) { Iteration iteration = (Iteration)controlStatement; Iterator<ResultItem> itrResultItem = iteration.resultItemsIterator(); addToResultItems(itrResultItem, resultItems); } else if (controlStatement instanceof IfStatement) { IfStatement ifStatement = (IfStatement)controlStatement; List<IfResult> results = ifStatement.getResults(); if (results != null) { for (IfResult result : results) { if (result.getResultItems() == null) { continue; } Iterator<ResultItem> itrResultItem = result.getResultItems().iterator(); addToResultItems(itrResultItem, resultItems); } } } else if (controlStatement instanceof SwitchStatement) { SwitchStatement switchStatement = (SwitchStatement)controlStatement; SwitchResults switchResults = switchStatement.getResults(); if (switchResults != null) { List<SwitchResult> results = switchResults.getResults(); if (results != null) { for (SwitchResult result : results) { if (result.getResultItems() == null) { continue; } Iterator<ResultItem> itrResultItem = result.getResultItems().iterator(); addToResultItems(itrResultItem, resultItems); } } List<ResultItem> defaultResult = switchResults.getDefaultResult(); if (defaultResult != null) { Iterator<ResultItem> itrResultItem = defaultResult.iterator(); addToResultItems(itrResultItem, resultItems); } } } return resultItems; } private void addToResultItems(Iterator<ResultItem> itrResultItem, List<Item> resultItems) { if (itrResultItem == null) { return; } if (resultItems == null) { return; } while (itrResultItem.hasNext()) { ResultItem resultItem = itrResultItem.next(); resultItems.add(resultItem); } } public void addAll(PresentationTier otherPresentationTier) { // view if (view == null || view.getWindows() == null) { view = otherPresentationTier.getView(); } else { if (otherPresentationTier.getView() != null) { getView().addAll(otherPresentationTier.getView()); } } // events if (events == null) { events = new ArrayList<Event>(); } if (otherPresentationTier.getEvents() != null) { events.addAll(otherPresentationTier.getEvents()); } // styles if (styles == null) { styles = new StyleSet(); } if (otherPresentationTier.getStyles() != null) { styles.addAll(otherPresentationTier.getStyles()); } } public Map<String, Event> getEventsMap() { return eventsMap; } public View getView() { return view; } public void setView(View view) { this.view = view; } public void setStyles(StyleSet styles) { this.styles = styles; } }