PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/servers/sip-presence/presence/server/subscription-sbb/src/main/java/org/mobicents/slee/sippresence/server/subscription/rules/OMAPresRuleDOMTransformer.java

http://mobicents.googlecode.com/
Java | 582 lines | 443 code | 48 blank | 91 comment | 217 complexity | d649eabfd4cd9140bc191c9e1dbe2cc5 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.slee.sippresence.server.subscription.rules;
  23. import java.net.URI;
  24. import java.util.ArrayList;
  25. import java.util.HashSet;
  26. import java.util.List;
  27. import java.util.Set;
  28. import javax.xml.parsers.ParserConfigurationException;
  29. import org.mobicents.xdm.common.util.dom.DomUtils;
  30. import org.openxdm.xcap.common.error.InternalServerErrorException;
  31. import org.w3c.dom.Document;
  32. import org.w3c.dom.Element;
  33. import org.w3c.dom.Node;
  34. import org.w3c.dom.NodeList;
  35. public class OMAPresRuleDOMTransformer implements
  36. OMAPresRuleTransformer<Document> {
  37. @Override
  38. public Document transform(Document content, OMAPresRule rule)
  39. throws InternalServerErrorException {
  40. if (!rule.hasTransformations()) {
  41. // nothing to transform
  42. return content;
  43. }
  44. // clone doc
  45. Document result = null;
  46. try {
  47. result = DomUtils.DOCUMENT_BUILDER_NS_AWARE_FACTORY
  48. .newDocumentBuilder().newDocument();
  49. } catch (ParserConfigurationException e) {
  50. throw new InternalServerErrorException(
  51. "failed to setup DOM builder", e);
  52. }
  53. Node presence = result.appendChild(result.importNode(
  54. content.getDocumentElement(), true));
  55. NodeList presenceChilds = presence.getChildNodes();
  56. Node presenceChild = null;
  57. String nodeName = null;
  58. boolean keepChild;
  59. Set<Node> nodesToRemove = null;
  60. for (int i = 0; i < presenceChilds.getLength(); i++) {
  61. presenceChild = presenceChilds.item(i);
  62. keepChild = true;
  63. if (presenceChild.getNodeType() == Node.ELEMENT_NODE) {
  64. nodeName = DomUtils.getElementName(presenceChild);
  65. if ((!rule.isProvideAllDevices() || !rule
  66. .isProvideAllAttributes()) && nodeName.equals("device")) {
  67. keepChild = keepDevice(presenceChild, rule);
  68. } else if ((!rule.isProvideAllPersons() || !rule
  69. .isProvideAllAttributes()) && nodeName.equals("person")) {
  70. keepChild = keepPerson(presenceChild, rule);
  71. } else if ((!rule.isProvideAllServices() || !rule
  72. .isProvideAllAttributes()) && nodeName.equals("tuple")) {
  73. keepChild = keepService(presenceChild, rule);
  74. } else {
  75. if (!rule.isProvideAllAttributes()) {
  76. keepChild = keepUnknownAttribute(nodeName,
  77. presenceChild.getNamespaceURI(), presenceChild,
  78. rule);
  79. }
  80. }
  81. }
  82. // TODO consider removing unneeded text nodes and namespaces
  83. // declared
  84. if (!keepChild) {
  85. if (nodesToRemove == null) {
  86. nodesToRemove = new HashSet<Node>();
  87. }
  88. nodesToRemove.add(presenceChild);
  89. }
  90. }
  91. if (nodesToRemove != null) {
  92. for (Node node : nodesToRemove) {
  93. node.getParentNode().removeChild(node);
  94. }
  95. }
  96. return result;
  97. }
  98. private boolean keepService(Node presenceChild, OMAPresRule rule) {
  99. boolean keepNode = rule.isProvideAllServices();
  100. NodeList nodeList = presenceChild.getChildNodes();
  101. Node node = null;
  102. String nodeName = null;
  103. List<Node> otherNodes = null;
  104. for (int i = 0; i < nodeList.getLength(); i++) {
  105. node = nodeList.item(i);
  106. if (node.getNodeType() == Node.ELEMENT_NODE) {
  107. nodeName = DomUtils.getElementName(node);
  108. if (nodeName.equals("class")) {
  109. if (keepNode) {
  110. continue;
  111. }
  112. if (rule.getProvideServiceClasses() != null
  113. && rule.getProvideServiceClasses().contains(
  114. node.getTextContent().trim())) {
  115. keepNode = true;
  116. if (rule.isProvideAllAttributes()) {
  117. return true;
  118. }
  119. }
  120. } else if (nodeName.equals("contact")) {
  121. if (keepNode) {
  122. continue;
  123. }
  124. if (rule.getProvideServiceServiceURIs() != null
  125. && rule.getProvideServiceServiceURIs().contains(
  126. node.getTextContent().trim())) {
  127. keepNode = true;
  128. if (rule.isProvideAllAttributes()) {
  129. return true;
  130. }
  131. continue;
  132. } else if (rule.getProvideServiceServiceURISchemes() != null
  133. && rule.getProvideServiceServiceURISchemes()
  134. .contains(
  135. URI.create(node.getTextContent().trim())
  136. .getScheme())) {
  137. keepNode = true;
  138. if (rule.isProvideAllAttributes()) {
  139. return true;
  140. }
  141. }
  142. } else if (nodeName.equals("id")) {
  143. if (keepNode) {
  144. continue;
  145. }
  146. if (rule.getProvideServiceOccurenceIds() != null
  147. && rule.getProvideServiceOccurenceIds().contains(
  148. node.getTextContent().trim())) {
  149. keepNode = true;
  150. if (rule.isProvideAllAttributes()) {
  151. return true;
  152. }
  153. }
  154. } else {
  155. if (!rule.isProvideAllAttributes()) {
  156. if (otherNodes == null) {
  157. otherNodes = new ArrayList<Node>();
  158. }
  159. otherNodes.add(node);
  160. }
  161. }
  162. }
  163. }
  164. if (!keepNode) {
  165. return false;
  166. }
  167. // filter the other nodes
  168. if (otherNodes != null) {
  169. for (Node otherNode : otherNodes) {
  170. if (!keepServiceAttribute(otherNode, rule)) {
  171. presenceChild.removeChild(otherNode);
  172. }
  173. }
  174. }
  175. return true;
  176. }
  177. private boolean keepServiceAttribute(Node node, OMAPresRule rule) {
  178. String nodeName = DomUtils.getElementName(node);
  179. String nodeNamespaceURI = node.getNamespaceURI();
  180. /*
  181. * The <contact>, <service-class> [9], <basic> status, and <timestamp>
  182. * elements in all <tuple> elements, if present, are provided to
  183. * watchers.
  184. */
  185. if (nodeNamespaceURI.equals("urn:ietf:params:xml:ns:pidf")) {
  186. // pidf
  187. if (nodeName.equals("status")) {
  188. return true;
  189. } else if (nodeName.equals("timestamp")) {
  190. return true;
  191. }
  192. } else if (nodeNamespaceURI
  193. .equals("urn:ietf:params:xml:ns:pidf:data-model")) {
  194. // data model
  195. if (nodeName.equals("note")) {
  196. return rule.isProvideNote();
  197. }
  198. else if (nodeName.equals("deviceID")) {
  199. return rule.isProvideDeviceID();
  200. }
  201. } else if (nodeNamespaceURI.equals("urn:ietf:params:xml:ns:pidf:rpid")) {
  202. // rpid
  203. if (nodeName.equals("class")) {
  204. return rule.isProvideClass();
  205. } else if (nodeName.equals("privacy")) {
  206. return rule.isProvidePrivacy();
  207. } else if (nodeName.equals("relationship")) {
  208. return rule.isProvideRelationship();
  209. } else if (nodeName.equals("service-class")) {
  210. return true;
  211. } else if (nodeName.equals("status-icon")) {
  212. return rule.isProvideStatusIcon();
  213. } else if (nodeName.equals("user-input")) {
  214. return keepUserInput(node, rule);
  215. }
  216. } else if (nodeNamespaceURI.equals("urn:oma:xml:prs:pidf:oma-pres")) {
  217. // oma
  218. if (nodeName.equals("willingness")) {
  219. return rule.isProvideWillingness();
  220. } else if (nodeName.equals("service-description")) {
  221. return true;
  222. } else if (nodeName.equals("barring-state")) {
  223. return rule.isProvideBarringState();
  224. } else if (nodeName.equals("registration-state")) {
  225. return rule.isProvideRegistrationState();
  226. } else if (nodeName.equals("session-participation")) {
  227. return rule.isProvideSessionParticipation();
  228. }
  229. } else if (nodeNamespaceURI
  230. .equals("urn:ietf:params:xml:ns:pidf:geopriv10")) {
  231. // geopriv
  232. if (nodeName.equals("geopriv")) {
  233. return rule.getProvideGeopriv() == GeoPrivTransformation.FULL;
  234. }
  235. }
  236. return keepUnknownAttribute(nodeName, nodeNamespaceURI, node, rule);
  237. }
  238. private boolean keepUserInput(Node node, OMAPresRule rule) {
  239. UserInputTransformation uti = rule.getProvideUserInput();
  240. if (uti == null) {
  241. return false;
  242. }
  243. /*
  244. * This permission controls access to the <user-input> element defined
  245. * in [9]. The name of the element providing this permission is
  246. * <provide-user-input>, and it is an enumerated integer type. Its value
  247. * defines what information is provided to watchers in person, device,
  248. * or service data elements:
  249. *
  250. * false: This value indicates that the <user-input> element is removed
  251. * from the document. It is assigned the numeric value of 0.
  252. *
  253. * bare: This value indicates that the <user-input> element is to be
  254. * retained. However, any "idle-threshold" and "since" attributes are to
  255. * be removed. This value is assigned the numeric value of 10.
  256. *
  257. * thresholds: This value indicates that the <user-input> element is to
  258. * be retained. However, only the "idle-threshold" attribute is to be
  259. * retained. This value is assigned the numeric value of 20.
  260. *
  261. * full: This value indicates that the <user-input> element is to be
  262. * retained, including any attributes. This value is assigned the
  263. * numeric value of 30.
  264. */
  265. final Element element = (Element) node;
  266. switch (uti) {
  267. case BARE:
  268. element.removeAttribute("last-input");
  269. element.removeAttribute("idle-threshold");
  270. return true;
  271. case THRESHOLDS:
  272. element.removeAttribute("last-input");
  273. return true;
  274. case FULL:
  275. return true;
  276. case FALSE:
  277. default:
  278. return false;
  279. }
  280. }
  281. private boolean keepPerson(Node presenceChild, OMAPresRule rule) {
  282. boolean keepNode = rule.isProvideAllPersons();
  283. NodeList nodeList = presenceChild.getChildNodes();
  284. Node node = null;
  285. String nodeName = null;
  286. List<Node> otherNodes = null;
  287. for (int i = 0; i < nodeList.getLength(); i++) {
  288. node = nodeList.item(i);
  289. if (node.getNodeType() == Node.ELEMENT_NODE) {
  290. nodeName = DomUtils.getElementName(node);
  291. if (nodeName.equals("class")) {
  292. if (keepNode) {
  293. continue;
  294. }
  295. if (rule.getProvidePersonClasses() != null
  296. && rule.getProvidePersonClasses().contains(
  297. node.getTextContent().trim())) {
  298. keepNode = true;
  299. if (rule.isProvideAllAttributes()) {
  300. return true;
  301. }
  302. }
  303. } else if (nodeName.equals("id")) {
  304. if (keepNode) {
  305. continue;
  306. }
  307. if (rule.getProvidePersonOccurenceIds() != null
  308. && rule.getProvidePersonOccurenceIds().contains(
  309. node.getTextContent().trim())) {
  310. keepNode = true;
  311. if (rule.isProvideAllAttributes()) {
  312. return true;
  313. }
  314. }
  315. } else {
  316. if (!rule.isProvideAllAttributes()) {
  317. if (otherNodes == null) {
  318. otherNodes = new ArrayList<Node>();
  319. }
  320. otherNodes.add(node);
  321. }
  322. }
  323. }
  324. }
  325. if (!keepNode) {
  326. return false;
  327. }
  328. if (otherNodes != null) {
  329. for (Node otherNode : otherNodes) {
  330. if (!keepPersonAttribute(otherNode, rule)) {
  331. presenceChild.removeChild(otherNode);
  332. }
  333. }
  334. }
  335. return true;
  336. }
  337. private boolean keepPersonAttribute(Node node, OMAPresRule rule) {
  338. String nodeName = DomUtils.getElementName(node);
  339. String nodeNamespaceURI = node.getNamespaceURI();
  340. /*
  341. * The <timestamp> element in all <person> elements, if present, is
  342. * provided to watchers.
  343. */
  344. if (nodeNamespaceURI
  345. .equals("urn:ietf:params:xml:ns:pidf:data-model")) {
  346. // data model
  347. if (nodeName.equals("timestamp")) {
  348. return true;
  349. }
  350. else if (nodeName.equals("note")) {
  351. return rule.isProvideNote();
  352. }
  353. } else if (nodeNamespaceURI.equals("urn:ietf:params:xml:ns:pidf:rpid")) {
  354. // rpid
  355. if (nodeName.equals("activities")) {
  356. return rule.isProvideActivities();
  357. } else if (nodeName.equals("class")) {
  358. return rule.isProvideClass();
  359. } else if (nodeName.equals("mood")) {
  360. return rule.isProvideMood();
  361. } else if (nodeName.equals("place-is")) {
  362. return rule.isProvidePlaceIs();
  363. } else if (nodeName.equals("place-type")) {
  364. return rule.isProvidePlaceType();
  365. } else if (nodeName.equals("privacy")) {
  366. return rule.isProvidePrivacy();
  367. } else if (nodeName.equals("sphere")) {
  368. return rule.isProvideSphere();
  369. } else if (nodeName.equals("status-icon")) {
  370. return rule.isProvideStatusIcon();
  371. } else if (nodeName.equals("time-offset")) {
  372. return rule.isProvideTimeOffset();
  373. } else if (nodeName.equals("user-input")) {
  374. return keepUserInput(node, rule);
  375. }
  376. } else if (nodeNamespaceURI.equals("urn:oma:xml:prs:pidf:oma-pres")) {
  377. // oma
  378. if (nodeName.equals("overriding-willingness")) {
  379. return rule.isProvideWillingness();
  380. }
  381. } else if (nodeNamespaceURI
  382. .equals("urn:ietf:params:xml:ns:pidf:geopriv10")) {
  383. // geopriv
  384. if (nodeName.equals("geopriv")) {
  385. return rule.getProvideGeopriv() == GeoPrivTransformation.FULL;
  386. }
  387. }
  388. return keepUnknownAttribute(nodeName, nodeNamespaceURI, node, rule);
  389. }
  390. private boolean keepDevice(Node presenceChild, OMAPresRule rule) {
  391. boolean keepNode = rule.isProvideAllDevices();
  392. NodeList nodeList = presenceChild.getChildNodes();
  393. Node node = null;
  394. String nodeName = null;
  395. List<Node> otherNodes = null;
  396. for (int i = 0; i < nodeList.getLength(); i++) {
  397. node = nodeList.item(i);
  398. if (node.getNodeType() == Node.ELEMENT_NODE) {
  399. nodeName = DomUtils.getElementName(node);
  400. if (nodeName.equals("class")) {
  401. if (keepNode) {
  402. continue;
  403. }
  404. if (rule.getProvideDeviceClasses() != null
  405. && rule.getProvideDeviceClasses().contains(
  406. node.getTextContent().trim())) {
  407. keepNode = true;
  408. if (rule.isProvideAllAttributes()) {
  409. return true;
  410. }
  411. }
  412. } else if (nodeName.equals("deviceID")) {
  413. if (keepNode) {
  414. continue;
  415. }
  416. if (rule.getProvideDeviceDeviceIDs() != null
  417. && rule.getProvideDeviceDeviceIDs().contains(
  418. node.getTextContent().trim())) {
  419. keepNode = true;
  420. if (rule.isProvideAllAttributes()) {
  421. return true;
  422. }
  423. }
  424. } else if (nodeName.equals("id")) {
  425. if (keepNode) {
  426. continue;
  427. }
  428. if (rule.getProvideDeviceOccurenceIds() != null
  429. && rule.getProvideDeviceOccurenceIds().contains(
  430. node.getTextContent().trim())) {
  431. keepNode = true;
  432. if (rule.isProvideAllAttributes()) {
  433. return true;
  434. }
  435. }
  436. } else {
  437. if (!rule.isProvideAllAttributes()) {
  438. if (otherNodes == null) {
  439. otherNodes = new ArrayList<Node>();
  440. }
  441. otherNodes.add(node);
  442. }
  443. }
  444. }
  445. }
  446. if (!keepNode) {
  447. return false;
  448. }
  449. if (otherNodes != null) {
  450. for (Node otherNode : otherNodes) {
  451. if (!keepDeviceAttribute(otherNode, rule)) {
  452. presenceChild.removeChild(otherNode);
  453. }
  454. }
  455. }
  456. return true;
  457. }
  458. private boolean keepDeviceAttribute(Node node, OMAPresRule rule) {
  459. String nodeName = DomUtils.getElementName(node);
  460. String nodeNamespaceURI = node.getNamespaceURI();
  461. /*
  462. * The <timestamp> and <deviceID> elements in all <device> elements, if
  463. * present, are provided to all watchers.
  464. */
  465. if (nodeNamespaceURI
  466. .equals("urn:ietf:params:xml:ns:pidf:data-model")) {
  467. // data model
  468. if (nodeName.equals("timestamp")) {
  469. return true;
  470. }
  471. else if (nodeName.equals("deviceID")) {
  472. return true;
  473. } else if (nodeName.equals("note")) {
  474. return rule.isProvideNote();
  475. }
  476. } else if (nodeNamespaceURI.equals("urn:ietf:params:xml:ns:pidf:rpid")) {
  477. // rpid
  478. if (nodeName.equals("class")) {
  479. return rule.isProvideClass();
  480. } else if (nodeName.equals("user-input")) {
  481. return keepUserInput(node, rule);
  482. }
  483. } else if (nodeNamespaceURI.equals("urn:oma:xml:prs:pidf:oma-pres")) {
  484. // oma
  485. if (nodeName.equals("network-availability")) {
  486. return rule.isProvideNetworkAvailability();
  487. }
  488. } else if (nodeNamespaceURI
  489. .equals("urn:ietf:params:xml:ns:pidf:geopriv10")) {
  490. // geopriv
  491. if (nodeName.equals("geopriv")) {
  492. return rule.getProvideGeopriv() == GeoPrivTransformation.FULL;
  493. }
  494. }
  495. return keepUnknownAttribute(nodeName, nodeNamespaceURI, node, rule);
  496. }
  497. private boolean keepUnknownAttribute(String nodeName,
  498. String nodeNamespaceURI, Node node, OMAPresRule rule) {
  499. // look for a name + namespace match in rule
  500. if (rule.getUnknownBooleanAttributes() != null) {
  501. for (UnknownBooleanAttributeTransformation ubat : rule
  502. .getUnknownBooleanAttributes()) {
  503. if (!ubat.getName().equals(nodeName)) {
  504. continue;
  505. }
  506. if (nodeNamespaceURI == null) {
  507. if (ubat.getNamespace() != null) {
  508. continue;
  509. }
  510. } else if (!nodeNamespaceURI.equals(ubat.getNamespace())) {
  511. continue;
  512. }
  513. // match, process childs
  514. // FIXME this sounds nonsense
  515. /*NodeList nodeList = node.getChildNodes();
  516. Node childNode = null;
  517. for (int i = 0; i < nodeList.getLength(); i++) {
  518. childNode = nodeList.item(i);
  519. if (childNode.getNodeType() == Node.ELEMENT_NODE) {
  520. if (!keepUnknownAttribute(
  521. DomUtils.getElementName(childNode),
  522. childNode.getNamespaceURI(), childNode, rule)) {
  523. node.removeChild(childNode);
  524. }
  525. }
  526. }*/
  527. // provide node
  528. return true;
  529. }
  530. }
  531. // no match, don't provide node
  532. return false;
  533. }
  534. }