1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.mapping.pattern;
\r
15 public class MappingRule {
\r
17 static final THashSet<Resource> EMPTY_SET = new THashSet<Resource>();
\r
19 THashMap<Resource, Resource> resourcesByDomains = new THashMap<Resource, Resource>();
\r
20 Collection<IConstraint> constraints = new ArrayList<IConstraint>();
\r
21 Collection<ConstraintGroup> constraintGroups = new ArrayList<ConstraintGroup>();
\r
23 static class ConstraintGroup {
\r
24 Collection<IConstraint> constraints;
\r
25 Collection<Resource> targets;
\r
26 Collection<Resource> dependencies;
\r
29 class DirectedRuleBuilder {
\r
30 THashSet<Resource> sourceResources = new THashSet<Resource>();
\r
31 THashSet<Resource> targetResources = new THashSet<Resource>();
\r
32 THashSet<IConstraint> sourceConstraints = new THashSet<IConstraint>();
\r
33 THashSet<IConstraint> targetConstraints = new THashSet<IConstraint>();
\r
34 TObjectIntHashMap<Resource> boundResources;
\r
37 Instruction root = new DummyInstruction();
\r
38 Instruction cur = root;
\r
40 public DirectedRuleBuilder(final THashSet<Resource> sourceDomains,
\r
41 TObjectIntHashMap<Resource> boundResources, int id) {
\r
42 this.boundResources = boundResources;
\r
45 // Classify resources
\r
47 resourcesByDomains.forEachEntry(new TObjectObjectProcedure<Resource, Resource>() {
\r
50 public boolean execute(Resource domain, Resource resource) {
\r
51 if(sourceDomains.contains(domain))
\r
52 sourceResources.add(resource);
\r
54 targetResources.add(resource);
\r
60 // Classify constraints
\r
62 for(IConstraint constraint : constraints) {
\r
63 if(sourceResources.containsAll(constraint.binds()))
\r
64 sourceConstraints.add(constraint);
\r
66 targetConstraints.add(constraint);
\r
71 IConstraint bestConstraint;
\r
73 private void findBestConstraint(THashSet<IConstraint> constraints) {
\r
75 bestConstraint = null;
\r
76 sourceConstraints.forEach(new TObjectProcedure<IConstraint>() {
\r
79 public boolean execute(IConstraint constraint) {
\r
80 int temp = constraint.isApplicable(boundResources);
\r
81 if(temp>bestValue) {
\r
83 bestConstraint = constraint;
\r
91 private void applyConstraint(THashSet<Resource> resources, IConstraint constraint) {
\r
92 THashSet<Resource> unbounded = new THashSet<Resource>();
\r
93 for(Resource r : constraint.binds())
\r
94 if(resources.remove(r)) {
\r
96 boundResources.put(r, id++);
\r
98 Instruction temp = constraint.createQueryInstruction(boundResources, unbounded);
\r
103 private void applyConstraints(THashSet<Resource> resources, THashSet<IConstraint> constraints) {
\r
104 while(!constraints.isEmpty()) {
\r
105 findBestConstraint(constraints);
\r
106 if(bestConstraint != null) {
\r
107 applyConstraint(resources, bestConstraint);
\r
108 constraints.remove(bestConstraint);
\r
111 throw new RuntimeException("Cannot form a directed mapping.");
\r
115 public void orderSourceConstraints() {
\r
116 applyConstraints(sourceResources, sourceConstraints);
\r
117 if(!sourceResources.isEmpty())
\r
118 throw new RuntimeException("Couldn't bind all source resources");
\r
121 public void orderTargetConstraints() {
\r
122 THashSet<ConstraintGroup> groups = new THashSet<ConstraintGroup>(constraintGroups);
\r
123 while(!groups.isEmpty()) {
\r
125 // Find a suitable group
\r
127 final Ref<ConstraintGroup> possibleGroup = new Ref<ConstraintGroup>();
\r
128 final Collection<ConstraintGroup> removableGroups = new ArrayList<ConstraintGroup>();
\r
129 groups.forEach(new TObjectProcedure<ConstraintGroup>() {
\r
132 public boolean execute(ConstraintGroup group) {
\r
133 for(Resource target : group.targets)
\r
134 if(boundResources.containsKey(target)) {
\r
135 removableGroups.add(group);
\r
138 for(Resource dep : group.dependencies)
\r
139 if(!boundResources.containsKey(dep))
\r
141 possibleGroup.value = group;
\r
146 groups.removeAll(removableGroups);
\r
147 if(possibleGroup.value == null) {
\r
148 if(!groups.isEmpty())
\r
149 throw new RuntimeException("Couldn't find a suitable group.");
\r
152 groups.remove(possibleGroup.value);
\r
153 ConstraintGroup group = possibleGroup.value;
\r
155 // Order group constraints
\r
157 THashSet<IConstraint> groupConstraints = new THashSet<IConstraint>();
\r
158 for(IConstraint constraint : group.constraints)
\r
159 if(targetConstraints.remove(constraint))
\r
160 groupConstraints.add(constraint);
\r
162 applyConstraints(targetResources, groupConstraints);
\r
164 // Apply other constraints
\r
166 final Collection<IConstraint> removableConstraints = new ArrayList<IConstraint>();
\r
167 targetConstraints.forEach(new TObjectProcedure<IConstraint>() {
\r
170 public boolean execute(IConstraint constraint) {
\r
171 for(Resource r : constraint.binds())
\r
172 if(!boundResources.containsKey(r))
\r
175 Instruction temp = constraint.createQueryInstruction(boundResources, EMPTY_SET);
\r
179 removableConstraints.add(constraint);
\r
184 targetConstraints.removeAll(removableConstraints);
\r
186 if(!targetResources.isEmpty())
\r
187 throw new RuntimeException("Couldn't bind all target resources");
\r