@Override public T instantiateDummy(final Relationship entity, final String entityType) throws FrameworkException { Map<String, Class<? extends RelationshipInterface>> entities = StructrApp.getConfiguration().getRelationshipEntities(); Class<T> relClass = (Class<T>) entities.get(entityType); T newRel = null; if (relClass != null) { try { newRel = relClass.newInstance(); newRel.init(factoryProfile.getSecurityContext(), entity); // let rel. know of its instantiation so it can cache its start- and end node ID. newRel.onRelationshipInstantiation(); } catch (Throwable t) { newRel = null; } } return newRel; }
@Override public void processMessage(final WebSocketMessage webSocketData) { final GraphObject obj = getGraphObject(webSocketData.getId()); String key = (String) webSocketData.getNodeData().get("key"); if (obj != null) { PropertyKey propertyKey = StructrApp.getConfiguration().getPropertyKeyForJSONName(obj.getClass(), key); PropertyConverter converter = propertyKey.inputConverter(getWebSocket().getSecurityContext()); Object value = obj.getProperty(propertyKey); if (converter != null) { try { value = converter.revert(value); } catch (FrameworkException ex) { getWebSocket() .send(MessageBuilder.status().code(400).message(ex.getMessage()).build(), true); } } webSocketData.setNodeData(key, value); // send only over local connection (no broadcast) getWebSocket().send(webSocketData, true); } else { getWebSocket().send(MessageBuilder.status().code(404).build(), true); } }
@Override public void indexPassiveProperties() { for (PropertyKey key : StructrApp.getConfiguration().getPropertySet(entityType, PropertyView.All)) { if (key.isPassivelyIndexed()) { key.index(this, this.getPropertyForIndexing(key)); } } }
/** * Return list of nodes which are not attached to a page and have no parent element (no incoming * CONTAINS rel) * * @param app * @param securityContext * @param webSocketData * @return * @throws FrameworkException */ protected static List<AbstractNode> getUnattachedNodes( final App app, final SecurityContext securityContext, final WebSocketMessage webSocketData) throws FrameworkException { final String sortOrder = webSocketData.getSortOrder(); final String sortKey = webSocketData.getSortKey(); final PropertyKey sortProperty = StructrApp.getConfiguration().getPropertyKeyForJSONName(DOMNode.class, sortKey); final Query query = StructrApp.getInstance(securityContext) .nodeQuery() .includeDeletedAndHidden() .sort(sortProperty) .order("desc".equals(sortOrder)); query.orTypes(DOMElement.class); query.orType(Content.class); query.orType(Template.class); // do search List<AbstractNode> filteredResults = new LinkedList(); List<? extends GraphObject> resultList = null; try (final Tx tx = app.tx()) { resultList = query.getAsList(); } catch (FrameworkException fex) { logger.warn("Exception occured", fex); } // determine which of the nodes have no incoming CONTAINS relationships and no page id for (GraphObject obj : resultList) { if (obj instanceof AbstractNode) { AbstractNode node = (AbstractNode) obj; if (!node.hasIncomingRelationships(DOMChildren.class) && node.getProperty(DOMNode.ownerDocument) == null && !(node instanceof ShadowDocument)) { filteredResults.add(node); } } } return filteredResults; }
public Transformation( final Class type, final String sourceName, final String targetName, final String inputFunction, final String outputFunction) { this.sourceName = sourceName; this.targetName = targetName; this.inputFunction = inputFunction; this.outputFunction = outputFunction; this.sourceProperty = StructrApp.getConfiguration().getPropertyKeyForJSONName(type, sourceName); this.targetProperty = new GenericProperty(targetName); }
private Class type(final String typeString) throws FrameworkException { Class type = null; final ConfigurationProvider config = StructrApp.getConfiguration(); if (typeString != null) { type = config.getNodeEntityClass(typeString); } if (type == null) { throw new FrameworkException(422, "Unknown type '" + typeString + "'"); } return type; }
@Override public T instantiateWithType( final Relationship relationship, final Class<T> relClass, final boolean isCreation) throws FrameworkException { logger.log(Level.FINEST, "Instantiate relationship with type {0}", relClass.getName()); SecurityContext securityContext = factoryProfile.getSecurityContext(); T newRel = null; try { newRel = relClass.newInstance(); } catch (Throwable t) { newRel = null; } if (newRel == null) { newRel = (T) StructrApp.getConfiguration().getFactoryDefinition().createGenericRelationship(); } newRel.init(securityContext, relationship); // try to set correct type property on relationship entity final String type = newRel.getProperty(GraphObject.type); if (type == null || (type != null && !type.equals(relClass.getSimpleName()))) { newRel.unlockReadOnlyPropertiesOnce(); newRel.setProperty(GraphObject.type, relClass.getSimpleName()); } newRel.onRelationshipInstantiation(); return newRel; }
// ----- interface GraphObject ----- @Override public Iterable<PropertyKey> getPropertyKeys(final String propertyView) { return StructrApp.getConfiguration().getPropertySet(this.getClass(), propertyView); }
private void extractAndSetValue( final NodeInterface obj, final Document doc, final String selector, final String mappedType, final String mappedAttribute, final String mappedAttributeFormat, final SourcePage subPage) throws FrameworkException { // If the sub pattern has a mapped attribute, set the extracted value if (StringUtils.isNotEmpty(mappedAttribute)) { // Extract the value for this sub pattern's selector final String ex = doc.select(selector).text(); final ConfigurationProvider config = StructrApp.getConfiguration(); final PropertyKey key = config.getPropertyKeyForJSONName(type(mappedType), mappedAttribute); if (key != null) { Object convertedValue = ex; final PropertyConverter inputConverter = key.inputConverter(securityContext); if (inputConverter != null) { final String locale = getProperty(mappedAttributeLocaleProperty); DecimalFormat decimalFormat = null; if (key instanceof DoubleProperty) { if (StringUtils.isNotBlank(locale)) { decimalFormat = (DecimalFormat) NumberFormat.getNumberInstance(new Locale(locale)); } else if (StringUtils.isNotBlank(mappedAttributeFormat)) { decimalFormat = new DecimalFormat(mappedAttributeFormat); } if (decimalFormat != null) { convertedValue = decimalFormat.format(convertedValue); } } else { convertedValue = inputConverter.convert(ex); } } obj.setProperty(key, convertedValue); } // If the sub pattern has no mapped attribute but a sub page defined, query the patterns of // the sub page } else if (subPage != null) { final String pageUrl = subPage.getProperty(SourcePage.url); final URI uri; try { uri = new URI(pageUrl); } catch (URISyntaxException ex) { throw new FrameworkException(422, "Unable to parse sub page url: " + pageUrl); } // This is the URL of the linked page derived from the enclosing selector final String subUrl = uri.getScheme() + "://" + uri.getAuthority() + doc.select(selector).attr("href"); // Extract the content of the linked page final String subContent = getContent(subUrl); // Parse the content into a document final Document subDoc = Jsoup.parse(subContent); final List<SourcePattern> subPagePatterns = subPage.getProperty(SourcePage.patterns); // Loop through all patterns of the sub page for (final SourcePattern subPagePattern : subPagePatterns) { final Map<String, Object> params = new HashMap<>(); params.put("document", subDoc); params.put("object", obj); subPagePattern.extract(params); // final String subPagePatternSelector = // subPagePattern.getProperty(SourcePattern.selectorProperty); // // // // Extract // final String subEx = subDoc.select(subPagePatternSelector).text(); // final String subPagePatternType = // subPagePattern.getProperty(SourcePattern.mappedTypeProperty); // // if (subPagePatternType != null) { // // // final Elements subParts = subDoc.select(subPagePatternSelector); // // final Long j = 1L; // // for (final Element subPart : subParts) { // // final NodeInterface subObj = create(subPagePatternType); // // final List<SourcePattern> subPagePatternPatterns = // subPagePattern.getProperty(SourcePattern.subPatternsProperty); // // for (final SourcePattern subPageSubPattern : subPagePatternPatterns) { // // // final String subPagePatternSelector = // subPageSubPattern.getProperty(SourcePattern.selectorProperty); // // // // final String subPageSubPatternSelector = subPagePatternSelector + ":nth-child(" + j // + ") > " + subPagePatternSelector; // // extractAndSetValue(subObj, subDoc, subSelector, mappedType, // subPatternMappedAttribute); // // // final String subSubEx = subDoc.select(subPageSubPatternSelector).text(); // // if (subSubEx != null && subSubEx != = '' && subPageSubPattern.mappedAttribute != // null) { // // final PropertyKey key = config.getPropertyKeyForJSONName(type(mappedType), // subPatternMappedAttribute); // if (key != null) { // // subObj.setProperty(key, subSubEx); // } // // } // // final String subPagePatternMappedAttribute = // subPagePattern.getProperty(SourcePattern.mappedAttributeProperty); // // final PropertyKey key = config.getPropertyKeyForJSONName(type(mappedType), // subPagePatternMappedAttribute); // if (key != null) { // // obj.setProperty(key, subSubEx); // } // // } // // } else { // // if (subEx != null && subEx != = '' && subPagePattern.mappedAttribute != null) { // obj[subPagePattern.mappedAttribute] = subEx; // } } } }
@Override public List<GraphObject> getData( final SecurityContext securityContext, final RenderContext renderContext, final String restQuery) throws FrameworkException { Map<Pattern, Class<? extends Resource>> resourceMap = new LinkedHashMap<>(); ResourceProvider resourceProvider = renderContext == null ? null : renderContext.getResourceProvider(); if (resourceProvider == null) { try { resourceProvider = UiResourceProvider.class.newInstance(); } catch (Throwable t) { logger.log(Level.SEVERE, "Couldn't establish a resource provider", t); return Collections.EMPTY_LIST; } } // inject resources resourceMap.putAll(resourceProvider.getResources()); Value<String> propertyView = new ThreadLocalPropertyView(); propertyView.set(securityContext, PropertyView.Ui); // initialize variables // mimic HTTP request HttpServletRequest request = new HttpServletRequestWrapper( renderContext == null ? securityContext.getRequest() : renderContext.getRequest()) { @Override public Enumeration<String> getParameterNames() { return new IteratorEnumeration(getParameterMap().keySet().iterator()); } @Override public String getParameter(String key) { String[] p = getParameterMap().get(key); return p != null ? p[0] : null; } @Override public Map<String, String[]> getParameterMap() { String[] parts = StringUtils.split(getQueryString(), "&"); Map<String, String[]> parameterMap = new HashMap(); for (String p : parts) { String[] kv = StringUtils.split(p, "="); if (kv.length > 1) { parameterMap.put(kv[0], new String[] {kv[1]}); } } return parameterMap; } @Override public String getQueryString() { return StringUtils.substringAfter(restQuery, "?"); } @Override public String getPathInfo() { return StringUtils.substringBefore(restQuery, "?"); } @Override public StringBuffer getRequestURL() { return new StringBuffer(restQuery); } }; // update request in security context securityContext.setRequest(request); // HttpServletResponse response = renderContext.getResponse(); Resource resource = ResourceHelper.applyViewTransformation( request, securityContext, ResourceHelper.optimizeNestedResourceChain( ResourceHelper.parsePath( securityContext, request, resourceMap, propertyView, GraphObject.id), GraphObject.id), propertyView); // TODO: decide if we need to rest the REST request here // securityContext.checkResourceAccess(request, resource.getResourceSignature(), // resource.getGrant(request, response), PropertyView.Ui); // add sorting & paging String pageSizeParameter = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_SIZE); String pageParameter = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_PAGE_NUMBER); String offsetId = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_OFFSET_ID); String sortOrder = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_ORDER); String sortKeyName = request.getParameter(JsonRestServlet.REQUEST_PARAMETER_SORT_KEY); boolean sortDescending = (sortOrder != null && "desc".equals(sortOrder.toLowerCase())); int pageSize = parseInt(pageSizeParameter, NodeFactory.DEFAULT_PAGE_SIZE); int page = parseInt(pageParameter, NodeFactory.DEFAULT_PAGE); PropertyKey sortKey = null; // set sort key if (sortKeyName != null) { Class<? extends GraphObject> type = resource.getEntityClass(); if (type == null) { // fallback to default implementation // if no type can be determined type = AbstractNode.class; } sortKey = StructrApp.getConfiguration().getPropertyKeyForDatabaseName(type, sortKeyName); } // do action Result result = resource.doGet(sortKey, sortDescending, pageSize, page, offsetId); result.setIsCollection(resource.isCollectionResource()); result.setIsPrimitiveArray(resource.isPrimitiveArray()); // Integer rawResultCount = (Integer) Services.getAttribute(NodeFactory.RAW_RESULT_COUNT + // Thread.currentThread().getId()); PagingHelper.addPagingParameter(result, pageSize, page); List<GraphObject> res = result.getResults(); if (renderContext != null) { renderContext.setResult(result); } return res != null ? res : Collections.EMPTY_LIST; }
private synchronized < A extends NodeInterface, B extends NodeInterface, R extends Relation<A, B, ?, ?>> R createRelationship( final A fromNode, final B toNode, final Class<R> relType, final PropertyMap properties) throws FrameworkException { final RelationshipFactory<R> factory = new RelationshipFactory(securityContext); final R template = instantiate(relType); final Node startNode = fromNode.getNode(); final Node endNode = toNode.getNode(); final Relationship rel = startNode.createRelationshipTo(endNode, template); final R newRel = factory.instantiate(rel); final Date now = new Date(); // logger.log(Level.INFO, "CREATING relationship {0}-[{1}]->{2}", new Object[] { // fromNode.getType(), newRel.getRelType(), toNode.getType() } ); if (newRel != null) { newRel.unlockReadOnlyPropertiesOnce(); newRel.setProperty(GraphObject.type, relType.getSimpleName()); // set UUID newRel.unlockReadOnlyPropertiesOnce(); newRel.setProperty(GraphObject.id, getNextUuid()); // set created date newRel.unlockReadOnlyPropertiesOnce(); newRel.setProperty(AbstractRelationship.createdDate, now); // set last modified date newRel.unlockReadOnlyPropertiesOnce(); newRel.setProperty(AbstractRelationship.lastModifiedDate, now); // Try to get the cascading delete flag from the domain specific relationship type newRel.unlockReadOnlyPropertiesOnce(); newRel.setProperty( AbstractRelationship.cascadeDelete, factory.instantiate(rel).getCascadingDeleteFlag()); // notify transaction handler TransactionCommand.relationshipCreated(newRel); if (properties != null) { for (Entry<PropertyKey, Object> entry : properties.entrySet()) { PropertyKey key = entry.getKey(); // on creation, writing of read-only properties should be possible if (key.isReadOnly() || key.isWriteOnce()) { newRel.unlockReadOnlyPropertiesOnce(); } newRel.setProperty(entry.getKey(), entry.getValue()); } } // notify relationship of its creation newRel.onRelationshipCreation(); // iterate post creation transformations for (Transformation<GraphObject> transformation : StructrApp.getConfiguration().getEntityCreationTransformations(newRel.getClass())) { transformation.apply(securityContext, newRel); } } return newRel; }
// ~--- methods -------------------------------------------------------- @Override public void processMessage(final WebSocketMessage webSocketData) { final String keyString = (String) webSocketData.getNodeData().get("key"); if (keyString == null) { logger.error("Unable to remove given object from collection: key is null"); getWebSocket().send(MessageBuilder.status().code(400).build(), true); } final String idToRemove = (String) webSocketData.getNodeData().get("idToRemove"); if (idToRemove == null) { logger.error("Unable to remove given object from collection: idToRemove is null"); getWebSocket().send(MessageBuilder.status().code(400).build(), true); } GraphObject obj = getNode(webSocketData.getId()); if (obj != null) { if (!((AbstractNode) obj).isGranted(Permission.write, getWebSocket().getSecurityContext())) { getWebSocket() .send(MessageBuilder.status().message("No write permission").code(400).build(), true); logger.warn( "No write permission for {} on {}", new Object[] {getWebSocket().getCurrentUser().toString(), obj.toString()}); return; } } if (obj == null) { // No node? Try to find relationship obj = getRelationship(webSocketData.getId()); } GraphObject objToRemove = getNode(idToRemove); if (obj != null && objToRemove != null) { try { PropertyKey key = StructrApp.getConfiguration().getPropertyKeyForJSONName(obj.getClass(), keyString); if (key != null) { List collection = (List) obj.getProperty(key); collection.remove(objToRemove); obj.setProperties(obj.getSecurityContext(), new PropertyMap(key, collection)); if (obj instanceof NodeInterface) { TransactionCommand.registerNodeCallback((NodeInterface) obj, callback); } else if (obj instanceof RelationshipInterface) { TransactionCommand.registerRelCallback((RelationshipInterface) obj, callback); } } } catch (FrameworkException ex) { logger.error("Unable to set properties: {}", ((FrameworkException) ex).toString()); getWebSocket().send(MessageBuilder.status().code(400).build(), true); } } else { logger.warn("Graph object with uuid {} not found.", webSocketData.getId()); getWebSocket().send(MessageBuilder.status().code(404).build(), true); } }
@Override public void processMessage(WebSocketMessage webSocketData) { final Map<String, Object> nodeData = webSocketData.getNodeData(); final String parentId = (String) nodeData.get("parentId"); final String childContent = (String) nodeData.get("childContent"); final String pageId = webSocketData.getPageId(); nodeData.remove("parentId"); if (pageId != null) { // check for parent ID before creating any nodes if (parentId == null) { getWebSocket() .send( MessageBuilder.status() .code(422) .message("Cannot add node without parentId") .build(), true); return; } // check if parent node with given ID exists final DOMNode parentNode = getDOMNode(parentId); if (parentNode == null) { getWebSocket() .send(MessageBuilder.status().code(404).message("Parent node not found").build(), true); return; } final Document document = getPage(pageId); if (document != null) { final String tagName = (String) nodeData.get("tagName"); final App app = StructrApp.getInstance(); nodeData.remove("tagName"); try { app.beginTx(); DOMNode newNode; if (tagName != null && !tagName.isEmpty()) { newNode = (DOMNode) document.createElement(tagName); } else { newNode = (DOMNode) document.createTextNode("#text"); } // append new node to parent if (newNode != null) { parentNode.appendChild(newNode); for (Entry entry : nodeData.entrySet()) { String key = (String) entry.getKey(); Object val = entry.getValue(); PropertyKey propertyKey = StructrApp.getConfiguration() .getPropertyKeyForDatabaseName(newNode.getClass(), key); if (propertyKey != null) { try { Object convertedValue = val; PropertyConverter inputConverter = propertyKey.inputConverter(SecurityContext.getSuperUserInstance()); if (inputConverter != null) { convertedValue = inputConverter.convert(val); } // newNode.unlockReadOnlyPropertiesOnce(); newNode.setProperty(propertyKey, convertedValue); } catch (FrameworkException fex) { logger.log( Level.WARNING, "Unable to set node property {0} of node {1} to {2}: {3}", new Object[] {propertyKey, newNode.getUuid(), val, fex.getMessage()}); } } } // create a child text node if content is given if (StringUtils.isNotBlank(childContent)) { DOMNode childNode = (DOMNode) document.createTextNode(childContent); if (newNode != null) { newNode.appendChild(childNode); } } } app.commitTx(); } catch (DOMException dex) { // send DOM exception getWebSocket() .send(MessageBuilder.status().code(422).message(dex.getMessage()).build(), true); } catch (FrameworkException ex) { Logger.getLogger(CreateAndAppendDOMNodeCommand.class.getName()) .log(Level.SEVERE, null, ex); } finally { app.finishTx(); } } else { getWebSocket() .send(MessageBuilder.status().code(404).message("Page not found").build(), true); } } else { getWebSocket() .send( MessageBuilder.status() .code(422) .message("Cannot create node without pageId") .build(), true); } }