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