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