예제 #1
0
 SortBySiblingBlock(Node def) throws RuleBaseException {
   super(def);
   before = def.query().exists("@before");
   String attrName = before ? "@before" : "@after";
   if (!"sibling".equals(def.query().single(attrName).value()))
     throw new RuleBaseException("sort block " + attrName + " must have value 'sibling'");
 }
예제 #2
0
 @Override
 public void verify() throws TransformException {
   ItemList targets = mod.nearest(NodeTarget.class).targets();
   List<Node> references = mod.references();
   ItemList records = mod.supplementQuery().all("sort-proxy");
   assert targets.size() == references.size();
   assert records.size() == references.size();
   for (int i = 0; i < targets.size(); i++) {
     Node target = targets.get(i).node();
     Node restoredProxy = references.get(i);
     ItemList items = query.runOn(mod.scope(target.query()));
     if (items.size() != 1)
       throw new TransformException(
           "sort by corresponding node must select one node per target, but instead selected "
               + items.size()
               + ": "
               + items);
     Node proxy = items.get(0).node();
     if (!restoredProxy.equals(proxy)) throw new TransformException("computed proxy changed");
     if (!proxy
         .query()
         .single(
             "(count(preceding::*) + count(ancestor::*)) eq xs:integer($_1/@position)",
             records.get(i))
         .booleanValue()) throw new SortingException("computed proxy moved");
   }
 }
예제 #3
0
 @Override
 public void restore() throws TransformException {
   ItemList targets = mod.nearest(NodeTarget.class).targets();
   values = new ArrayList<Pair<String, Item>>(targets.size());
   for (Node node : targets.nodes()) {
     ItemList items = query.runOn(mod.scope(node.query()));
     if (items.size() != 1)
       throw new TransformException(
           "sort by value query did not select exactly one item: " + items);
     values.add(Pair.of(node.query().single("@xml:id").value(), items.get(0).toAtomicItem()));
   }
 }
예제 #4
0
 @AllowAttributes({"priority", "by", "as", "before", "after"})
 @Override
 public Block define(Node def) throws RuleBaseException {
   int numDirectives = def.query().single("count(@by | @as | @before | @after)").intValue();
   if (numDirectives > 1)
     throw new RuleBaseException(
         "sort block specified with more than one of @by, @as, @before and @after");
   if (numDirectives < 1)
     throw new RuleBaseException("sort block specified without any @by, @as, @before or @after");
   if (def.query().exists("@by")) return new SortByValueBlock(def);
   else if (def.query().exists("@as")) return new SortByProxyBlock(def);
   else return new SortBySiblingBlock(def);
 }
예제 #5
0
 @Override
 void resolveOrder(Mod.Builder modBuilder, Node node) throws TransformException {
   ItemList siblings = query.runOn(modBuilder.customScope(node.query().single("..").query()));
   for (Node sibling : siblings.nodes()) {
     if (!node.query().single(".. is $_1/..", sibling).booleanValue())
       throw new TransformException("query selected non-sibling node: " + sibling);
     modBuilder.reference(sibling);
   }
   modBuilder
       .supplement()
       .elem("sort-siblings")
       .attr("run-length", siblings.size())
       .end("sort-siblings");
 }
예제 #6
0
 @Override
 void resolveOrder(Mod.Builder modBuilder, Node node) throws TransformException {
   ItemList items = query.runOn(modBuilder.customScope(node.query()));
   if (items.size() != 1)
     throw new TransformException(
         "sort by value must select one value per target, but instead selected "
             + items.size()
             + ": "
             + items);
   modBuilder
       .supplement()
       .elem("sort-value")
       .attr("refid", node.query().single("@xml:id").value())
       .text(items.get(0).value())
       .end("sort-value");
 }
예제 #7
0
 @Test(expected = TransformException.class)
 public void resolveOrderBadQuery() throws RuleBaseException, TransformException {
   SortBlock block = define("<sort as='corresponding'>*</sort>");
   Node uc1 = content.query().single("/id('uc1')").node();
   setModBuilderCustomScope(uc1.query());
   block.resolveOrder(modBuilder, uc1);
 }
예제 #8
0
 @Test(expected = TransformException.class)
 public void resolveOrderNotSibling() throws RuleBaseException, TransformException {
   SortBlock block = define("<sort before='sibling'>.//uml:operation</sort>");
   Node cname = content.query().single("/id('cname')").node();
   Node uc1 = content.query().single("/id('uc1')").node();
   setModBuilderCustomScope(uc1.query());
   block.resolveOrder(modBuilder, cname);
 }
예제 #9
0
 @Test
 public void resolveOrder() throws RuleBaseException, TransformException {
   SortBlock block = define("<sort by='ascending'>@name</sort>");
   Node m1 = content.query().single("/id('m1')").node();
   setModBuilderCustomScope(m1.query());
   supplement();
   block.resolveOrder(modBuilder, m1);
   checkSupplement("<sort-value refid='m1'>start</sort-value>");
 }
예제 #10
0
 @Override
 public void verify() throws TransformException {
   for (Pair<Node, List<Node>> pair : siblingsByTarget) {
     Node target = pair.first;
     List<Node> storedSiblings = pair.second;
     for (Node sibling : storedSiblings) {
       if (!target.query().single(".. is $_1/..", sibling).booleanValue())
         throw new TransformException(
             "previously selected node is no longer a sibling: " + sibling);
     }
     List<Node> actualSiblings =
         query.runOn(mod.scope(target.query().single("..").query())).nodes().asList();
     if (!actualSiblings.equals(storedSiblings))
       throw new TransformException(
           "sibling list changed for target " + target.query().single("@xml:id").value());
     // No need to check sibling order, since any change in the node's document will trigger a
     // sort.
   }
 }
예제 #11
0
 @Override
 void resolveOrder(Mod.Builder modBuilder, Node node) throws TransformException {
   // TODO: see if we can resolve /id in global scope while keeping node context
   ItemList items = query.runOn(modBuilder.customScope(node.query()));
   if (items.size() != 1)
     throw new TransformException(
         "sort by corresponding node must select one node per target, but instead selected "
             + items.size()
             + ": "
             + items);
   Node proxy = items.get(0).node();
   modBuilder.reference(proxy);
   modBuilder
       .supplement()
       .elem("sort-proxy")
       .attr(
           "position", proxy.query().single("count(preceding::*) + count(ancestor::*)").value())
       .end("sort-proxy");
 }
예제 #12
0
 SortBlock(Node def) throws RuleBaseException {
   Item priorityItem = def.query().optional("@priority");
   try {
     priority = priorityItem.extant() ? priorityItem.intValue() : 0;
   } catch (DatabaseException e) {
     throw new RuleBaseException(
         "sort block specified bad priority '" + priorityItem.value() + "'", e);
   }
   query = new Query.Items(def);
 }
예제 #13
0
 SortByValueBlock(Node def) throws RuleBaseException {
   super(def);
   // TODO: support collations
   String direction = def.query().single("@by").value();
   if ("ascending".equals(direction)) ascending = true;
   else if ("descending".equals(direction)) ascending = false;
   else
     throw new RuleBaseException(
         "sort block @by must have value 'ascending' or 'descending', got '" + direction + "'");
 }
예제 #14
0
 @Test
 public void resolveOrderEmpty() throws RuleBaseException, TransformException {
   SortBlock block = define("<sort before='sibling'>()</sort>");
   Node cname = content.query().single("/id('cname')").node();
   Node uc1 = content.query().single("/id('uc1')").node();
   setModBuilderCustomScope(uc1.query());
   supplement();
   block.resolveOrder(modBuilder, cname);
   checkSupplement("<sort-siblings run-length='0'/>");
 }
예제 #15
0
 @Test
 public void resolveOrder1() throws RuleBaseException, TransformException {
   SortBlock block = define("<sort after='sibling'>uml:name</sort>");
   Node comp1 = content.query().single("/id('comp1')").node();
   Node uc1 = content.query().single("/id('uc1')").node();
   setModBuilderCustomScope(uc1.query());
   reference(content.query().single("/id('cname')").node());
   supplement();
   block.resolveOrder(modBuilder, comp1);
   checkSupplement("<sort-siblings run-length='1'/>");
 }
예제 #16
0
 @Test
 public void resolveOrder() throws RuleBaseException, TransformException {
   SortBlock block = define("<sort as='corresponding'>$source</sort>");
   Node um1 = content.query().single("/id('um1')").node();
   Node m1 = content.query().single("/id('m1')").node();
   setModBuilderCustomScope(um1.query().let("$source", m1));
   reference(m1);
   supplement();
   block.resolveOrder(modBuilder, um1);
   checkSupplement("<sort-proxy position='1'/>");
 }
예제 #17
0
 @SuppressWarnings("unchecked")
 @Test(expected = TransformException.class)
 public void verifyNotSibling() throws RuleBaseException, TransformException {
   Node uc1 = content.query().single("/id('uc1')").node();
   Node comp1 = content.query().single("/id('comp1')").node();
   Node um1 = content.query().single("/id('um1')").node();
   setModScope(uc1.query());
   SortBySiblingBlock block = define("<sort before='sibling'>.//uml:method</sort>");
   SortBySiblingBlock.SortBySiblingSeg seg =
       (SortBySiblingBlock.SortBySiblingSeg) block.createSeg(mod);
   seg.siblingsByTarget =
       Arrays.<Pair<Node, List<Node>>>asList(new Pair[] {Pair.of(comp1, Arrays.asList(um1))});
   seg.verify();
 }
예제 #18
0
 @SuppressWarnings("unchecked")
 @Test
 public void verify() throws RuleBaseException, TransformException {
   Node uc1 = content.query().single("/id('uc1')").node();
   Node comp1 = content.query().single("/id('comp1')").node();
   Node comp2 = content.query().single("/id('comp2')").node();
   Node cname = content.query().single("/id('cname')").node();
   setModScope(uc1.query());
   SortBySiblingBlock block = define("<sort before='sibling'>uml:name</sort>");
   SortBySiblingBlock.SortBySiblingSeg seg =
       (SortBySiblingBlock.SortBySiblingSeg) block.createSeg(mod);
   seg.siblingsByTarget =
       Arrays.<Pair<Node, List<Node>>>asList(
           new Pair[] {
             Pair.of(comp1, Arrays.asList(cname)), Pair.of(comp2, Arrays.asList(cname))
           });
   seg.verify();
 }
예제 #19
0
 private void runVerifyScenario(String proxyid, String modData)
     throws TransformException, RuleBaseException {
   Node um1 = content.query().single("/id('um1')").node();
   Node m1 = content.query().single("/id('m1')").node();
   setModNearestAncestorImplementing(
       NodeTarget.class,
       new NodeTarget() {
         public ItemList targets() throws TransformException {
           return content.query().all("/id('um1')");
         }
       });
   setModData(modData);
   setModReferences(content.query().single("/id($_1)", proxyid).node());
   setModScope(um1.query().let("$source", m1));
   SortByProxyBlock block = define("<sort as='corresponding'>$source</sort>");
   SortByProxyBlock.SortByProxySeg seg = (SortByProxyBlock.SortByProxySeg) block.createSeg(mod);
   seg.proxies = new ArrayList<Pair<String, Node>>();
   seg.proxies.add(Pair.of("um1", mod.references().get(0)));
   seg.verify();
 }
예제 #20
0
 SortByProxyBlock(Node def) throws RuleBaseException {
   super(def);
   if (!"corresponding".equals(def.query().single("@as").value()))
     throw new RuleBaseException("sort block @as must have value 'corresponding'");
 }