--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.diagram.adapter;\r
+\r
+import java.awt.Shape;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;\r
+import org.simantics.databoard.util.Bean;\r
+import org.simantics.datatypes.literal.Font;\r
+import org.simantics.datatypes.literal.RGB;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
+import org.simantics.db.common.request.ResourceRead;\r
+import org.simantics.db.common.request.TernaryRead;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.Variables;\r
+import org.simantics.db.procedure.AsyncProcedure;\r
+import org.simantics.diagram.content.ResourceTerminal;\r
+import org.simantics.diagram.flag.AbstractFlagType;\r
+import org.simantics.diagram.flag.BasicFlagType;\r
+import org.simantics.diagram.flag.FlagSceneGraph;\r
+import org.simantics.diagram.flag.FlagUtil;\r
+import org.simantics.diagram.flag.IFlagType;\r
+import org.simantics.diagram.flag.IFlagType.FlagInfo;\r
+import org.simantics.diagram.flag.IFlagTypeReader;\r
+import org.simantics.diagram.function.All;\r
+import org.simantics.diagram.function.PredefinedVariables;\r
+import org.simantics.diagram.query.DiagramRequests;\r
+import org.simantics.diagram.query.FlagTables;\r
+import org.simantics.diagram.query.FlagTypeFilter;\r
+import org.simantics.diagram.query.FlagTypeFilters;\r
+import org.simantics.diagram.query.FlagTypeVisual;\r
+import org.simantics.diagram.query.FlagTypeVisuals;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.diagram.synchronization.CompositeHintSynchronizer;\r
+import org.simantics.diagram.synchronization.IHintSynchronizer;\r
+import org.simantics.diagram.synchronization.SynchronizationHints;\r
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
+import org.simantics.diagram.synchronization.graph.FlagSynchronizer;\r
+import org.simantics.diagram.synchronization.graph.TransformSynchronizer;\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.Topology.Terminal;\r
+import org.simantics.g2d.element.ElementClass;\r
+import org.simantics.g2d.element.ElementUtils;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.TextEditor;\r
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
+import org.simantics.g2d.elementclass.FlagClass;\r
+import org.simantics.g2d.elementclass.FlagClass.Mode;\r
+import org.simantics.g2d.elementclass.FlagHandler;\r
+import org.simantics.g2d.utils.Alignment;\r
+import org.simantics.g2d.utils.geom.DirectionSet;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.modeling.template2d.ontology.Template2dResource;\r
+import org.simantics.structural2.modelingRules.IModelingRules;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class FlagClassFactory extends SyncElementFactory {\r
+\r
+ private static final Bean[] NO_BEANS = {};\r
+\r
+ private static final IHintSynchronizer HINT_SYNCHRONIZER = new CompositeHintSynchronizer(FlagSynchronizer.INSTANCE, TransformSynchronizer.INSTANCE);\r
+\r
+ public static ElementClass createFlagClass(Resource elementClass, Resource terminalResource) {\r
+ Terminal terminal = new ResourceTerminal(terminalResource, new AffineTransform(), DirectionSet.ANY);\r
+ return FlagClass.create(terminal, FlagSceneGraph.INSTANCE).newClassWith(new StaticObjectAdapter(elementClass));\r
+ }\r
+\r
+ @Override\r
+ public void create(AsyncReadGraph graph, ICanvasContext canvas, IDiagram diagram, Resource elementType, AsyncProcedure<ElementClass> procedure) {\r
+ DiagramResource DIA = graph.getService(DiagramResource.class);\r
+ procedure.execute(graph, createFlagClass(DIA.Flag, DIA.Flag_Terminal));\r
+ }\r
+\r
+ @Override\r
+ public void load(ReadGraph g, ICanvasContext canvas, IDiagram diagram, Resource flag, IElement e) throws DatabaseException {\r
+ Layer0 l0 = g.getService(Layer0.class);\r
+ DiagramResource dr = g.getService(DiagramResource.class);\r
+\r
+ ElementClass ec = e.getElementClass();\r
+ final FlagHandler fh = ec.getSingleItem(FlagHandler.class);\r
+\r
+ fh.connectData(e, flag, FlagUtil.getPossibleCounterpart(g, flag));\r
+ fh.setExternal(e, FlagUtil.isExternal(g, flag));\r
+\r
+ TextEditor ed = ec.getAtMostOneItemOfClass(TextEditor.class);\r
+ if (ed != null) {\r
+ final Session session = g.getSession();\r
+ ed.setModifier(e, new TextEditor.Modifier() {\r
+ @Override\r
+ public String getValue(IElement element) {\r
+ String s = ElementUtils.getText(element);\r
+ return s != null ? s : "";\r
+ }\r
+\r
+ @Override\r
+ public String isValid(IElement element, String text) {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void modify(final IElement element, final String text) {\r
+ final Resource flag = (Resource) ElementUtils.getObject(element);\r
+ try {\r
+ session.syncRequest(new WriteRequest() {\r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ DiagramGraphUtil.setRelatedValue(graph, flag, l0.HasLabel, l0.String, text, Bindings.STRING);\r
+ Resource otherFlag = FlagUtil.getPossibleCounterpart(graph, flag);\r
+ if (otherFlag != null)\r
+ DiagramGraphUtil.setRelatedValue(graph, otherFlag, l0.HasLabel, l0.String, text, Bindings.STRING);\r
+ }\r
+ });\r
+ } catch (DatabaseException e) {\r
+ ErrorLogger.defaultLogError("Flag label editing failed, see exception for details.", e);\r
+ }\r
+ }\r
+ });\r
+ }\r
+\r
+ Resource diagramRuntime = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE);\r
+ AffineTransform at = DiagramGraphUtil.getDynamicAffineTransform(g, diagramRuntime, flag);\r
+ ElementUtils.setTransform(e, at);\r
+\r
+ String label = g.getPossibleRelatedValue(flag, l0.HasLabel);\r
+ if (label == null)\r
+ label = "";\r
+ ElementUtils.setText(e, label);\r
+\r
+ boolean shapeIsSet = false;\r
+ boolean flagTextIsSet = false;\r
+ boolean flagTypeIsSet = false;\r
+ boolean textAreaIsSet = false;\r
+\r
+ // Defaults\r
+ e.setHint(FlagClass.KEY_TEXT_HORIZONTAL_ALIGN, Alignment.LEADING);\r
+ e.setHint(FlagClass.KEY_TEXT_VERTICAL_ALIGN, Alignment.CENTER);\r
+\r
+ IModelingRules modelingRules = diagram.getHint(DiagramModelHints.KEY_MODELING_RULES);\r
+ if (modelingRules != null) {\r
+ Resource connectionType = DiagramGraphUtil.getConnectionTypeForFlag(g, flag);\r
+ IFlagTypeReader ftr = null;\r
+ if (connectionType != null) {\r
+ //System.out.println("FLAG " + NameUtils.getSafeName(g, flag) + ", CONNECTION TYPE " + NameUtils.getSafeName(g, connectionType));\r
+ ftr = g.getPossibleAdapter(connectionType, IFlagTypeReader.class);\r
+ }\r
+ if (ftr == null) {\r
+ //System.out.println("FLAG " + NameUtils.getSafeName(g, flag) + ", NO CONNECTION TYPE");\r
+ ftr = g.getPossibleAdapter(flag, IFlagTypeReader.class);\r
+ }\r
+\r
+ if (ftr != null) {\r
+ IFlagType ft = ftr.read(g, flag, modelingRules);\r
+\r
+ FlagInfo info = ft.getInfo(g);\r
+\r
+ Shape shape = info.getShape();\r
+ if (shape != null) {\r
+ e.setHint(FlagClass.KEY_SHAPE, shape);\r
+ shapeIsSet = true;\r
+ }\r
+\r
+ FlagClass.Type type = info.getType();\r
+ if (type != null) {\r
+ e.setHint(FlagClass.KEY_FLAG_TYPE, type);\r
+ flagTypeIsSet = true;\r
+ }\r
+\r
+ String[] flagText = info.getText();\r
+ if (flagText != null) {\r
+ e.setHint(FlagClass.KEY_FLAG_TEXT, flagText);\r
+ flagTextIsSet = true;\r
+ }\r
+\r
+ if (info.getTextArea() != null) {\r
+ e.setHint(FlagClass.KEY_FLAG_TEXT_AREA, info.getTextArea());\r
+ textAreaIsSet = true;\r
+ }\r
+\r
+ if (info.getHorizontalAlignment() != null)\r
+ e.setHint(FlagClass.KEY_TEXT_HORIZONTAL_ALIGN, info.getHorizontalAlignment());\r
+ if (info.getVerticalAlignment() != null)\r
+ e.setHint(FlagClass.KEY_TEXT_VERTICAL_ALIGN, info.getVerticalAlignment());\r
+ }\r
+ }\r
+\r
+ if (!flagTypeIsSet)\r
+ // Fall back to reading flag type from a property.\r
+ e.setHint(FlagClass.KEY_FLAG_TYPE, DiagramGraphUtil.toFlagType(dr, g.getPossibleObject(flag, dr.HasFlagType), FlagClass.Type.In));\r
+ if (!flagTextIsSet)\r
+// e.setHint(FlagClass.KEY_FLAG_TEXT, new String[] { label });\r
+ e.setHint(FlagClass.KEY_FLAG_TEXT, g.syncRequest(DiagramRequests.getFlagText(flag)));\r
+ if (!textAreaIsSet) {\r
+ FlagClass.Type type = e.getHint(FlagClass.KEY_FLAG_TYPE);\r
+ Mode mode = AbstractFlagType.getMode(g, flag);\r
+ e.setHint(FlagClass.KEY_FLAG_TEXT_AREA, BasicFlagType.getArea(type, mode));\r
+ }\r
+ if (!shapeIsSet) {\r
+ FlagClass.Type type = e.getHint(FlagClass.KEY_FLAG_TYPE);\r
+ Mode mode = AbstractFlagType.getMode(g, flag);\r
+ e.setHint(FlagClass.KEY_SHAPE, BasicFlagType.getShape(type, mode));\r
+ }\r
+\r
+ e.setHint(SynchronizationHints.HINT_SYNCHRONIZER, HINT_SYNCHRONIZER);\r
+ e.setHint(FlagSceneGraph.KEY_FLAG_VISUALS, NO_BEANS);\r
+\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+\r
+ Resource template = diagramRuntime != null ? All.getTemplate(g, diagramRuntime) : null;\r
+ Resource flagTable = getFlagTable(g, template, flag);\r
+\r
+ if (template != null && flagTable != null) {\r
+\r
+ Resource flagTypeVisual = getVisualOfFlag(g, template, flagTable, flag);\r
+ if (flagTypeVisual != null) {\r
+ Template2dResource TEMPLATE2D = Template2dResource.getInstance(g);\r
+ float tableWidth = g.getRelatedValue(flagTable, TEMPLATE2D.FlagTable_HasWidth, Bindings.FLOAT);\r
+ Resource align = g.getPossibleObject(flagTable, TEMPLATE2D.FlagTable_HasAlignment);\r
+ float height = g.getRelatedValue(flagTable, TEMPLATE2D.FlagTable_HasRowHeigth, Bindings.FLOAT);\r
+ float halfHeight = height / 2;\r
+ float horizontalOffset = tableWidth;\r
+\r
+ if (align != null) {\r
+ if (align.equals(TEMPLATE2D.FlagTable_Alignment_Left)) {\r
+ horizontalOffset = 0.0f;\r
+ } else if (align.equals(TEMPLATE2D.FlagTable_Alignment_Right)) {\r
+ tableWidth = -tableWidth;\r
+ horizontalOffset = -horizontalOffset;\r
+ }\r
+ }\r
+\r
+ Collection<Resource> monitorsAndTexts = g.getObjects(flagTypeVisual, L0.ConsistsOf);\r
+ List<Bean> flagVisuals = Collections.emptyList(); \r
+ if (!monitorsAndTexts.isEmpty()) {\r
+ flagVisuals = new ArrayList<Bean>(monitorsAndTexts.size());\r
+\r
+ ModelingResources MOD = ModelingResources.getInstance(g);\r
+ Resource diagramResource = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);\r
+ Resource compositeResource = g.getSingleObject(diagramResource, MOD.DiagramToComposite);\r
+ Variable compositeVariable = Variables.getVariable(g, compositeResource);\r
+\r
+ for (Resource visual : monitorsAndTexts) {\r
+ if (!acceptVisual(g, flag, visual))\r
+ continue;\r
+\r
+ if (g.isInstanceOf(visual, DIA.Scenegraph_Monitor)) {\r
+ FlagTextInfo i = g.syncRequest(new ReadFlagTextInfo(visual), TransientCacheListener.<FlagTextInfo>instance());\r
+ FlagTextInfo monitorInfo = (FlagTextInfo) i.clone();\r
+ if (monitorInfo.transform != null)\r
+ monitorInfo.transform[4] += horizontalOffset;\r
+\r
+ String path = g.getRelatedValue(visual, DIA.Scenegraph_Monitor_reference, Bindings.STRING);\r
+ String value = "";\r
+ if (path != null && path.length() > 0) {\r
+ value = evaluatePath(g,flag,path);\r
+ }\r
+ monitorInfo.text = value;\r
+ monitorInfo.id = Long.toString(visual.getResourceId());\r
+\r
+ flagVisuals.add(monitorInfo);\r
+ } else if (g.isInstanceOf(visual, DIA.Scenegraph_Text)) {\r
+ FlagTextInfo i = g.syncRequest(new ReadFlagTextInfo(visual), TransientCacheListener.<FlagTextInfo>instance());\r
+ FlagTextInfo info = (FlagTextInfo) i.clone();\r
+ if (info.transform != null)\r
+ info.transform[4] += horizontalOffset;\r
+\r
+ String path = g.getRelatedValue(visual, DIA.Scenegraph_Text_text, Bindings.STRING);\r
+ if (path != null && path.length() > 0) {\r
+ info.text = path;\r
+ }\r
+ info.id = Long.toString(visual.getResourceId());\r
+\r
+ flagVisuals.add(info);\r
+ } else if (g.isInstanceOf(visual, DIA.Scenegraph_SVGImage)) {\r
+ SVGImageInfo info = g.syncRequest(new ReadSVGImageInfo(visual, compositeResource, compositeVariable), TransientCacheListener.<SVGImageInfo>instance());\r
+ flagVisuals.add(info);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (flagVisuals.size() > 0) {\r
+ // Make sure that the flag shape is set to something that\r
+ // should contain the flag visual to make selection borders\r
+ // work properly.\r
+ Rectangle2D newShape = new Rectangle2D.Double();\r
+ newShape.setFrameFromDiagonal(0, -halfHeight, tableWidth, halfHeight);\r
+ e.setHint(FlagClass.KEY_SHAPE, newShape);\r
+ e.setHint(FlagSceneGraph.KEY_FLAG_VISUALS, flagVisuals.toArray(NO_BEANS));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private static String evaluatePath(ReadGraph graph, Resource resource, String path) throws DatabaseException{\r
+ Variable resourceVariable = Variables.getPossibleVariable(graph, resource);\r
+ if (resourceVariable == null)\r
+ return "";\r
+ return evaluatePath(graph, resource, resourceVariable, path);\r
+ }\r
+\r
+ private static String evaluatePath(ReadGraph graph, Resource resource, Variable resourceVariable, String path) throws DatabaseException{\r
+ PredefinedVariables vars = PredefinedVariables.getInstance();\r
+ Variable property = vars.getVariable(graph, path, resource, resourceVariable);\r
+ if (property == null)\r
+ return "";\r
+ Object value = property.getPossibleValue(graph);\r
+ if (value == null || !(value instanceof String))\r
+ return "";\r
+ return value.toString();\r
+ }\r
+\r
+ static class ReadSVGImageInfo extends TernaryRead<Resource, Resource, Variable, SVGImageInfo> {\r
+\r
+ public ReadSVGImageInfo(Resource svgImageNode, Resource composite, Variable compositeVariable) {\r
+ super(svgImageNode, composite, compositeVariable);\r
+ }\r
+\r
+ @Override\r
+ public SVGImageInfo perform(ReadGraph graph) throws DatabaseException {\r
+ SVGImageInfo info = new SVGImageInfo();\r
+ DiagramResource DIA = DiagramResource.getInstance(graph);\r
+ info.id = Long.toString(parameter.getResourceId());\r
+ Resource document = graph.getPossibleObject(parameter, DIA.Scenegraph_SVGImage_document);\r
+ if (document != null) {\r
+ Template2dResource TMPL = Template2dResource.getInstance(graph);\r
+ String path = graph.getPossibleRelatedValue(document, TMPL.Profiles_VariableReference_path, Bindings.STRING);\r
+ if (path != null) {\r
+ String svg = evaluatePath(graph, parameter2, parameter3, path);\r
+ if (svg != null && !svg.isEmpty())\r
+ info.svgDocument = svg;\r
+ //System.out.println("svgDocument: " + info.svgDocument);\r
+ }\r
+ }\r
+ info.transform = graph.getPossibleRelatedValue(parameter, DIA.Scenegraph_SVGImage_transform, Bindings.DOUBLE_ARRAY);\r
+ return info;\r
+ }\r
+\r
+ }\r
+\r
+ static class ReadFlagTextInfo extends ResourceRead<FlagTextInfo> {\r
+\r
+ public ReadFlagTextInfo(Resource textNode) {\r
+ super(textNode);\r
+ }\r
+\r
+ @Override\r
+ public FlagTextInfo perform(ReadGraph graph) throws DatabaseException {\r
+ return createTextInfo(graph, resource);\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * @param g\r
+ * @param visual\r
+ * @return\r
+ * @throws DatabaseException\r
+ * @throws RuntimeBindingConstructionException\r
+ */\r
+ private static FlagTextInfo createTextInfo(ReadGraph g, Resource visual) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ //Template2d TEMPLATE2D = Template2d.getInstance(g);\r
+ //Layer0 L0 = Layer0.getInstance(g);\r
+\r
+ FlagTextInfo info = new FlagTextInfo();\r
+ info.id = Long.toString(visual.getResourceId());\r
+\r
+ info.font = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_font, Bindings.getBindingUnchecked(Font.class));\r
+ info.color = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_color, RGB.Integer.BINDING/*Bindings.getBindingUnchecked(RGB.Integer.class)*/);\r
+ info.borderColor = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_borderColor, RGB.Integer.BINDING/*Bindings.getBindingUnchecked(RGB.Integer.class)*/);\r
+ info.backgroundColor = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_backgroundColor, RGB.Integer.BINDING/*Bindings.getBindingUnchecked(RGB.Integer.class)*/);\r
+ Float width = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_width, Bindings.getBindingUnchecked(Float.class));\r
+ if (width != null)\r
+ info.width = width;\r
+\r
+ Float borderWidth = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_borderWidth, Bindings.getBindingUnchecked(Float.class));\r
+ if (borderWidth != null)\r
+ info.borderWidth = borderWidth;\r
+\r
+ Boolean wrapText = g.getRelatedValue2(visual, DIA.Scenegraph_AbstractText_wrapText, Bindings.BOOLEAN);\r
+ if (wrapText != null)\r
+ info.wrapText = wrapText; \r
+\r
+ info.hAlignment = Alignment.LEADING;\r
+ Byte hAlignment = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_horizontalAlignment, Bindings.BYTE);\r
+ if (hAlignment != null) {\r
+ if (hAlignment == 1)\r
+ info.hAlignment = Alignment.TRAILING;\r
+ else if (hAlignment == 2)\r
+ info.hAlignment = Alignment.CENTER;\r
+ }\r
+\r
+ info.vAlignment = Alignment.LEADING;\r
+ Byte vAlignment = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_verticalAlignment, Bindings.BYTE);\r
+ if (vAlignment != null) {\r
+ if (vAlignment == 1)\r
+ info.vAlignment = Alignment.TRAILING;\r
+ else if (vAlignment == 2)\r
+ info.vAlignment = Alignment.CENTER;\r
+ else if (vAlignment == 3)\r
+ info.vAlignment = Alignment.BASELINE;\r
+ }\r
+\r
+ info.transform = g.getPossibleRelatedValue2(visual, DIA.Scenegraph_AbstractText_transform, Bindings.getBindingUnchecked(double[].class));\r
+ return info;\r
+ }\r
+\r
+ private static Resource getFlagTable(ReadGraph g, Resource template, Resource flag) throws DatabaseException {\r
+ if (template == null || flag == null)\r
+ return null;\r
+\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ String tableName = g.getPossibleRelatedValue(flag, DIA.Flag_HasIOTableBinding, Bindings.STRING);\r
+ if (tableName == null)\r
+ return null;\r
+\r
+ Map<String, Resource> flagTables = g.syncRequest(new FlagTables(template), TransientCacheListener.<Map<String, Resource>>instance());\r
+ return flagTables.get(tableName);\r
+ }\r
+\r
+ private Resource getVisualOfFlag(ReadGraph g, Resource template, Resource flagTable, Resource flag) throws DatabaseException {\r
+ if (template == null || flagTable == null || flag == null)\r
+ return null;\r
+\r
+ // First make sure that there are possible visuals.\r
+ // There's no point in proceeding if no visuals exist.\r
+ List<FlagTypeVisual> flagTypeVisuals = g.syncRequest( new FlagTypeVisuals(flagTable),\r
+ TransientCacheListener.<List<FlagTypeVisual>>instance());\r
+ if (flagTypeVisuals == null || flagTypeVisuals.isEmpty())\r
+ return null;\r
+\r
+ Variable flagVariable = Variables.getPossibleVariable(g, flag);\r
+ if (flagVariable == null)\r
+ return null;\r
+\r
+ for (FlagTypeVisual visual : flagTypeVisuals) {\r
+ Resource visualComposite = visual.getVisualComposite();\r
+\r
+ String filterReference = visual.getFilteredPropertyReference();\r
+ if (filterReference == null || filterReference.isEmpty())\r
+ return visualComposite;\r
+\r
+ String filterPattern = visual.getFilterPattern();\r
+ if (filterPattern == null || filterPattern.isEmpty())\r
+ return visualComposite;\r
+\r
+ String value = evaluatePath(g, flag, flagVariable, filterReference);\r
+ if (value == null)\r
+ return visualComposite;\r
+\r
+ try {\r
+ if (!Pattern.matches(filterPattern, value)) {\r
+ // filter is defined but property don't match\r
+ continue;\r
+ }\r
+ } catch (PatternSyntaxException ex) {\r
+ ErrorLogger.defaultLogError(ex);\r
+ continue;\r
+ }\r
+\r
+ return visualComposite;\r
+ }\r
+\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * @param graph\r
+ * @param flag the flag to which to apply the filter reference paths\r
+ * @param visual the visual to look for filters from\r
+ * @return <code>true</code> if filter passes, <code>false</code> if not\r
+ * @throws DatabaseException\r
+ */\r
+ private boolean acceptVisual(ReadGraph graph, Resource flag, Resource visual) throws DatabaseException {\r
+ List<FlagTypeFilter> filters = graph.syncRequest(new FlagTypeFilters(visual),\r
+ TransientCacheListener.<List<FlagTypeFilter>>instance());\r
+ if (filters.isEmpty())\r
+ return true;\r
+\r
+ Variable flagVariable = Variables.getPossibleVariable(graph, flag);\r
+ if (flagVariable == null)\r
+ return false;\r
+\r
+ for (FlagTypeFilter filter : filters) {\r
+ String reference = filter.getReference();\r
+ if (reference == null || reference.isEmpty())\r
+ continue;\r
+\r
+ String pattern = filter.getPattern();\r
+ if (pattern == null || pattern.isEmpty())\r
+ continue;\r
+\r
+ String value = evaluatePath(graph, flag, flagVariable, reference);\r
+ if (value == null)\r
+ continue;\r
+\r
+ try {\r
+ if (Pattern.matches(pattern, value) == filter.isMatchRequired()) {\r
+ return true;\r
+ }\r
+ } catch (PatternSyntaxException ex) {\r
+ ErrorLogger.defaultLogError(ex);\r
+ continue;\r
+ }\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+}
\ No newline at end of file