1 # More Complex Interface Mapping MavenStyleProject - The Cascade
  2 [Back to Index ../](../index.md)
  3 
  4 # More Complex Interface Mapping MavenStyleProject - The Cascade
  5 
  6 Previously we showed probably the minimal useful mapping with S32Array
  7 
  8 The HaarCascade example has multiple nested interfaces representing data
  9 structures involving various nested structs and unions
 10 
 11 ```java
 12 public interface Cascade extends Buffer {
 13     int width();
 14     void width(int width);
 15     int height();
 16     void height(int height);
 17     interface Feature extends Buffer.StructChild {
 18         int id();
 19         float threshold();
 20         void id(int id);
 21         void threshold(float threshold);
 22         interface LinkOrValue extends Buffer.StructChild {
 23             interface Anon extends Buffer.UnionChild {
 24                 int featureId();
 25                 void featureId(int featureId);
 26                 float value();
 27                 void value(float value);
 28             }
 29             boolean hasValue();
 30             void hasValue(boolean hasValue);
 31             Anon anon();
 32         }
 33         LinkOrValue left();
 34         LinkOrValue right();
 35         interface Rect extends Buffer.StructChild {
 36             byte x();
 37             byte y();
 38             byte width();
 39             byte height();
 40             float weight();
 41             void x(byte x);
 42             void y(byte y);
 43             void width(byte width);
 44             void height(byte height);
 45             void weight(float height);
 46         }
 47         Rect rect(long idx);
 48     }
 49     int featureCount();
 50     void featureCount(int featureCount);
 51     Feature feature(long idx);
 52     interface Stage extends Buffer.StructChild {
 53         float threshold();
 54         short firstTreeId();
 55         short treeCount();
 56         int id();
 57         void id(int id);
 58         void threshold(float threshold);
 59         void firstTreeId(short firstTreeId);
 60         void treeCount(short treeCount);
 61     }
 62 
 63     int stageCount();
 64     void stageCount(int stageCount);
 65     Stage stage(long idx);
 66     interface Tree extends Buffer.StructChild {
 67         void id(int id);
 68         void firstFeatureId(short firstFeatureId);
 69         void featureCount(short featureCount);
 70         int id();
 71         short firstFeatureId();
 72         short featureCount();
 73     }
 74     int treeCount();
 75     void treeCount(int treeCount);
 76     Tree tree(long idx);
 77     Schema<Cascade> schema = Schema.of(Cascade.class, cascade -> cascade
 78             .fields("width", "height")
 79             .arrayLen("featureCount")
 80                 .array("feature", feature -> feature
 81                     .field("id")
 82                     .field("threshold")
 83                     .fields("left", "right", linkOrValue -> linkOrValue
 84                             .field("hasValue")
 85                             .pad(3)
 86                             .field("anon", anon -> anon
 87                                .field("featureId")
 88                                .field("value")
 89                             )
 90                     )
 91                     .array("rect", 3, rect -> rect
 92                        .field("x")
 93                        .field("y")
 94                        .field("width")
 95                        .field("height").
 96                        .field("weight"))
 97             )
 98             .arrayLen("treeCount")
 99                 .array("tree", tree -> tree
100                    .field("id")
101                    .field("featureCount")
102                    .field("firstFeatureId")
103                 )
104             .arrayLen("stageCount")
105                 .array("stage", stage -> stage
106                    .field("id")
107                    .field("threshold")
108                    .field("treeCount")
109                    .field("firstTreeId"))
110     );
111 }
112 ```
113 
114 Another great advantage of using interfaces is that we can choose
115 to re implement the interface in any was we see fit.
116 
117 For example we load  HaarCascades from XML files.
118 We therefore can create an implementation of the Cascade interface which just
119 loads the XML DOM... stores them in arrays and the interface methods just delegate to
120 the appropriately wrapped  w3c.Node tree nodes ;)
121 
122 If we know we are using Java backend we can actually
123 just pass the XMLCascade implementation directly to the backend...
124 
125 Actually the Cascade `create` method takes an existing
126 implementation of a Cascade and clones it.
127 So we can just pass it an XMLHaarCascade ;)
128 
129 So we build an XMLCascade then pass it to the `create` method of the iface
130 mapped Cascade
131 
132 ```java
133    XMLHaarCascadeModel haarCascade = XMLHaarCascadeModel.load(
134         ViolaJonesRaw.class.getResourceAsStream("haarcascade_frontalface_default.xml"));
135 
136    assert haarCascade instanceof Cascade; // Here it is just an interface
137 
138    Cascade cascade = Cascade.create(accelerator, haarCascade);
139 
140    // Now it can be used on the GPU
141 ```
142 
143 The implementation is currently hand crafted, but this could easily be automated.
144 
145 ```java
146  import java.lang.invoke.MethodHandles;
147 
148 static Cascade create(MethodHandles.Lookup lookup,BufferAllocator bufferAllocator, XMLHaarCascadeModel haarCascade) {
149 
150   Cascade cascade = bufferAllocator.allocate(SegmentMapper.of(lookup, Cascade.class,
151           JAVA_INT.withName("width"),
152           JAVA_INT.withName("height"),
153           JAVA_INT.withName("featureCount"),
154           sequenceLayout(haarCascade.features.size(), Feature.layout.withName(Feature.class.getSimpleName())).withName("feature"),
155           JAVA_INT.withName("stageCount"),
156           sequenceLayout(haarCascade.stages.size(), Stage.layout.withName(Stage.class.getSimpleName())).withName("stage"),
157           JAVA_INT.withName("treeCount"),
158           sequenceLayout(haarCascade.trees.size(), Tree.layout.withName(Tree.class.getSimpleName())).withName("tree")
159   ));
160   cascade.width(haarCascade.width());
161   cascade.height(haarCascade.height());
162   cascade.featureCount(haarCascade.features.size());
163   cascade.stageCount(haarCascade.stages.size());
164   cascade.treeCount(haarCascade.trees.size());
165   for (int idx = 0; idx < haarCascade.features.size(); idx++) {
166     Cascade.Feature cascadeFeature = cascade.feature(idx);
167     var haarfeature = haarCascade.features.get(idx);
168     cascadeFeature.id(haarfeature.id());
169     cascadeFeature.threshold(haarfeature.threshold());
170     Cascade.Feature.LinkOrValue cascadeLeft = cascadeFeature.left();
171     cascadeLeft.hasValue(haarfeature.left.hasValue());
172     if (haarfeature.left.hasValue()) {
173       cascadeLeft.anon().value(haarfeature.left.value());
174     } else {
175       cascadeLeft.anon().value(haarfeature.left.featureId());
176     }
177     Cascade.Feature.LinkOrValue cascadeRight = cascadeFeature.right();
178     cascadeRight.hasValue(haarfeature.right.hasValue());
179     if (haarfeature.right.hasValue()) {
180       cascadeRight.anon().value(haarfeature.right.value());
181     } else {
182       cascadeRight.anon().featureId(haarfeature.right.featureId());
183     }
184     for (int r = 0; r < 3; r++) {
185       var haarrect = haarfeature.rects[r];
186       if (haarrect != null) {
187         Cascade.Feature.Rect cascadeRect = cascadeFeature.rect(r);
188         cascadeRect.x(haarrect.x());
189         cascadeRect.y(haarrect.y());
190         cascadeRect.width(haarrect.width());
191         cascadeRect.height(haarrect.height());
192         cascadeRect.weight(haarrect.weight());
193       }
194     }
195   }
196   for (XMLHaarCascadeModel.Stage haarstage : haarCascade.stages) {
197     Cascade.Stage cascadeStage = cascade.stage(haarstage.id);
198     cascadeStage.id(haarstage.id());
199     cascadeStage.threshold(haarstage.threshold());
200     cascadeStage.firstTreeId(haarstage.firstTreeId());
201     cascadeStage.treeCount(haarstage.treeCount());
202   }
203 
204   for (XMLHaarCascadeModel.Tree haarTree : haarCascade.trees) {
205     Cascade.Tree cascadeTree = cascade.tree(haarTree.id());
206     cascadeTree.id(haarTree.id());
207     cascadeTree.firstFeatureId(haarTree.firstFeatureId());
208     cascadeTree.featureCount(haarTree.featureCount());
209   }
210   return cascade;
211 }
212 ```
213