use of org.structr.core.entity.Relation in project structr by structr.
the class AbstractMinifiedFile method getMaxPosition.
public static int getMaxPosition(final AbstractMinifiedFile thisFile) {
final Class<Relation> type = StructrApp.getConfiguration().getRelationshipEntityClass("AbstractMinifiedFileMINIFICATIONFile");
final PropertyKey<Integer> key = StructrApp.key(type, "position");
int max = -1;
for (final Relation neighbor : AbstractMinifiedFile.getSortedRelationships(thisFile)) {
max = Math.max(max, neighbor.getProperty(key));
}
return max;
}
use of org.structr.core.entity.Relation in project structr by structr.
the class AbstractMinifiedFile method getConcatenatedSource.
public static String getConcatenatedSource(final AbstractMinifiedFile thisFile) throws FrameworkException, IOException {
final Class<Relation> type = StructrApp.getConfiguration().getRelationshipEntityClass("AbstractMinifiedFileMINIFICATIONFile");
final PropertyKey<Integer> key = StructrApp.key(type, "position");
final StringBuilder concatenatedSource = new StringBuilder();
int cnt = 0;
for (Relation rel : AbstractMinifiedFile.getSortedRelationships(thisFile)) {
final File src = (File) rel.getTargetNode();
concatenatedSource.append(FileUtils.readFileToString(src.getFileOnDisk(), Charset.forName("utf-8")));
// compact the relationships (if necessary)
if (rel.getProperty(key) != cnt) {
rel.setProperty(key, cnt);
}
cnt++;
}
return concatenatedSource.toString();
}
use of org.structr.core.entity.Relation in project structr by structr.
the class Image method getScaledImage.
/**
* Get (down-)scaled image of this image
*
* If no scaled image of the requested size exists or the image is newer than the scaled image, create a new one.
*
* Default behaviour is to make the scaled image complete fit inside a rectangle of maxWidth x maxHeight.
*
* @param maxWidth
* @param maxHeight
* @param cropToFit if true, scale down until the shorter edge fits inside the rectangle, and then crop
*
* @return scaled image
*/
public static Image getScaledImage(final Image thisImage, final int maxWidth, final int maxHeight, final boolean cropToFit) {
final Class<Relation> thumbnailRel = StructrApp.getConfiguration().getRelationshipEntityClass("ImageTHUMBNAILImage");
final Iterable<Relation> thumbnailRelationships = thisImage.getOutgoingRelationships(thumbnailRel);
final SecurityContext securityContext = thisImage.getSecurityContext();
final List<Image> oldThumbnails = new LinkedList<>();
Image thumbnail = null;
final Image originalImage = thisImage;
final Integer origWidth = originalImage.getWidth();
final Integer origHeight = originalImage.getHeight();
final Long currentChecksum = originalImage.getChecksum();
Long newChecksum = 0L;
if (currentChecksum == null || currentChecksum == 0) {
try {
newChecksum = FileHelper.getChecksum(originalImage.getFileOnDisk());
if (newChecksum == null || newChecksum == 0) {
logger.warn("Unable to calculate checksum of {}", originalImage.getName());
return null;
}
} catch (IOException ex) {
logger.warn("Unable to calculate checksum of {}: {}", originalImage.getName(), ex.getMessage());
}
} else {
newChecksum = currentChecksum;
}
// Read Exif and GPS data from image and update properties
ImageHelper.getExifData(originalImage);
// Return self if SVG image
final String _contentType = thisImage.getContentType();
if (_contentType != null && (_contentType.startsWith("image/svg") || (_contentType.startsWith("image/") && _contentType.endsWith("icon")))) {
return thisImage;
}
if (origWidth != null && origHeight != null && thumbnailRelationships != null) {
for (final Relation r : thumbnailRelationships) {
final Integer w = r.getProperty(StructrApp.key(Image.class, "width"));
final Integer h = r.getProperty(StructrApp.key(Image.class, "height"));
if (w != null && h != null) {
// orginal image is equal or smaller than requested size
if (((w == maxWidth) && (h <= maxHeight)) || ((w <= maxWidth) && (h == maxHeight)) || ((origWidth <= w) && (origHeight <= h))) {
thumbnail = (Image) r.getTargetNode();
// Use thumbnail only if checksum of original image matches with stored checksum
final Long storedChecksum = r.getProperty(StructrApp.key(Image.class, "checksum"));
if (storedChecksum != null && storedChecksum.equals(newChecksum)) {
return thumbnail;
} else {
oldThumbnails.add(thumbnail);
}
}
}
}
}
if (originalImage.getIsCreatingThumb()) {
logger.debug("Another thumbnail is being created - waiting....");
} else {
try {
// No thumbnail exists, or thumbnail was too old, so let's create a new one
logger.debug("Creating thumbnail for {} (w={} h={} crop={})", new Object[] { getName(), maxWidth, maxHeight, cropToFit });
originalImage.unlockSystemPropertiesOnce();
originalImage.setIsCreatingThumb(true);
final App app = StructrApp.getInstance();
originalImage.unlockSystemPropertiesOnce();
originalImage.setProperty(StructrApp.key(File.class, "checksum"), newChecksum);
final Thumbnail thumbnailData = ImageHelper.createThumbnail(originalImage, maxWidth, maxHeight, cropToFit);
if (thumbnailData != null) {
final Integer tnWidth = thumbnailData.getWidth();
final Integer tnHeight = thumbnailData.getHeight();
byte[] data = null;
try {
data = thumbnailData.getBytes();
final String thumbnailName = ImageHelper.getThumbnailName(originalImage.getName(), tnWidth, tnHeight);
// create thumbnail node
thumbnail = ImageHelper.createImageNode(securityContext, data, "image/" + Thumbnail.defaultFormat, Image.class, thumbnailName, true);
} catch (IOException ex) {
logger.warn("Could not create thumbnail image for " + getUuid(), ex);
}
if (thumbnail != null && data != null) {
// Create a thumbnail relationship
final PropertyMap relProperties = new PropertyMap();
relProperties.put(StructrApp.key(Image.class, "width"), tnWidth);
relProperties.put(StructrApp.key(Image.class, "height"), tnHeight);
relProperties.put(StructrApp.key(Image.class, "checksum"), newChecksum);
app.create(originalImage, thumbnail, thumbnailRel, relProperties);
final PropertyMap properties = new PropertyMap();
properties.put(StructrApp.key(Image.class, "width"), tnWidth);
properties.put(StructrApp.key(Image.class, "height"), tnHeight);
properties.put(StructrApp.key(AbstractNode.class, "hidden"), originalImage.getProperty(AbstractNode.hidden));
properties.put(StructrApp.key(AbstractNode.class, "visibleToAuthenticatedUsers"), originalImage.getProperty(AbstractNode.visibleToAuthenticatedUsers));
properties.put(StructrApp.key(AbstractNode.class, "visibleToPublicUsers"), originalImage.getProperty(AbstractNode.visibleToPublicUsers));
properties.put(StructrApp.key(File.class, "size"), Long.valueOf(data.length));
properties.put(StructrApp.key(AbstractNode.class, "owner"), originalImage.getProperty(AbstractNode.owner));
properties.put(StructrApp.key(File.class, "parent"), originalImage.getParent());
properties.put(StructrApp.key(File.class, "hasParent"), originalImage.getProperty(StructrApp.key(Image.class, "hasParent")));
thumbnail.unlockSystemPropertiesOnce();
thumbnail.setProperties(securityContext, properties);
// Delete outdated thumbnails
for (final Image tn : oldThumbnails) {
app.delete(tn);
}
}
} else {
logger.debug("Could not create thumbnail for image {} ({})", getName(), getUuid());
}
originalImage.unlockSystemPropertiesOnce();
originalImage.setIsCreatingThumb(false);
} catch (FrameworkException fex) {
logger.warn("Unable to create thumbnail for " + getUuid(), fex);
}
}
return thumbnail;
}
use of org.structr.core.entity.Relation in project structr by structr.
the class IdDeserializationStrategy method deserialize.
@Override
public T deserialize(final SecurityContext securityContext, final Class<T> type, final S source, final Object context) throws FrameworkException {
final App app = StructrApp.getInstance(securityContext);
if (source != null) {
if (source instanceof Map) {
final Map<String, Object> properties = (Map<String, Object>) source;
Class<T> actualType = type;
if (actualType != null && actualType.isInterface()) {
// (creation wouldn't work otherwise anyway)
if (properties.containsKey(NodeInterface.type.jsonName())) {
final String typeFromInput = properties.get(NodeInterface.type.jsonName()).toString();
actualType = StructrApp.getConfiguration().getNodeEntityClass(typeFromInput);
// reset type on failed check
if (actualType == null) {
actualType = type;
}
}
}
final PropertyMap convertedProperties = PropertyMap.inputTypeToJavaType(securityContext, actualType, properties);
final Set<PropertyKey> allProperties = StructrApp.getConfiguration().getPropertySet(type, "all");
final Map<String, Object> foreignProps = new HashMap<>();
T relatedNode = null;
// If property map contains the uuid, search only for uuid
if (convertedProperties.containsKey(GraphObject.id)) {
relatedNode = (T) app.getNodeById(convertedProperties.get(GraphObject.id));
if (relatedNode != null) {
if (!SearchCommand.isTypeAssignableFromOtherType(type, relatedNode.getClass())) {
throw new FrameworkException(422, "Node type mismatch", new TypeToken(type.getSimpleName(), null, type.getSimpleName()));
}
for (final PropertyKey key : convertedProperties.keySet()) {
if (!key.isUnique() && !key.isCompound() && !isIdentifying(actualType, key) && !allProperties.contains(key)) {
// store "foreign" properties (those that are to be set on the newly created relationship
foreignProps.put(key.jsonName(), properties.get(key.jsonName()));
}
}
// node found, remove UUID
convertedProperties.remove(GraphObject.id);
}
} else {
final PropertyMap uniqueKeyValues = new PropertyMap();
for (final PropertyKey key : convertedProperties.keySet()) {
if (key.isUnique() || key.isCompound() || isIdentifying(actualType, key)) {
uniqueKeyValues.put(key, convertedProperties.get(key));
} else if (!allProperties.contains(key)) {
// store "foreign" properties (those that are to be set on the newly created relationship
foreignProps.put(key.jsonName(), properties.get(key.jsonName()));
}
}
// (this is quite similar to the Cypher MERGE command),
if (!uniqueKeyValues.isEmpty()) {
final List<T> possibleResults = app.nodeQuery(type).and(uniqueKeyValues).getAsList();
final int num = possibleResults.size();
switch(num) {
case 0:
// not found => will be created
break;
case 1:
relatedNode = possibleResults.get(0);
break;
default:
// more than one => not unique??
throw new FrameworkException(422, concat("Unable to resolve related node of type ", type.getSimpleName(), ", ambiguous result: found ", num, " nodes for the given property set."));
}
} else {
// throw exception here?
}
}
if (relatedNode == null) {
// no related node found, should we create one?
if (relationProperty != null) {
final Relation relation = relationProperty.getRelation();
if (relationProperty.doAutocreate()) {
return app.create(type, convertedProperties);
} else {
throw new FrameworkException(422, concat("Cannot create ", relation.getOtherType(type).getSimpleName(), ": no matching ", type.getSimpleName(), " found for the given property set ", convertedProperties, " and autoCreate has a value of ", relationProperty.getAutocreateFlagName()));
}
}
// FIXME: when can the relationProperty be null at all?
throw new FrameworkException(500, concat("Unable to resolve related node of type ", type.getSimpleName(), ", no relation defined."));
} else {
// set properties on related node?
if (!convertedProperties.isEmpty()) {
setProperties(securityContext, relatedNode, convertedProperties);
}
if (foreignProps.isEmpty()) {
return relatedNode;
} else {
return (T) new EntityAndPropertiesContainer(relatedNode, foreignProps);
}
}
} else if (type.isAssignableFrom(source.getClass())) {
return (T) source;
} else {
// interpret source as a raw ID string and fetch entity
final GraphObject obj = app.getNodeById(source.toString());
if (obj != null && !type.isAssignableFrom(obj.getClass())) {
throw new FrameworkException(422, "Node type mismatch", new TypeToken(obj.getClass().getSimpleName(), null, type.getSimpleName()));
}
return (T) obj;
}
}
return null;
}
use of org.structr.core.entity.Relation in project structr by structr.
the class SchemaResource method getSchemaOverviewResult.
// ----- public static methods -----
public static Result getSchemaOverviewResult() throws FrameworkException {
final List<GraphObjectMap> resultList = new LinkedList<>();
final ConfigurationProvider config = StructrApp.getConfiguration();
// extract types from ModuleService
final Set<String> nodeEntityKeys = config.getNodeEntities().keySet();
final Set<String> relEntityKeys = config.getRelationshipEntities().keySet();
Set<String> entityKeys = new HashSet<>();
entityKeys.addAll(nodeEntityKeys);
entityKeys.addAll(relEntityKeys);
for (String rawType : entityKeys) {
// create & add schema information
Class type = SchemaHelper.getEntityClassForRawType(rawType);
GraphObjectMap schema = new GraphObjectMap();
resultList.add(schema);
if (type != null) {
String url = "/".concat(rawType);
final boolean isRel = AbstractRelationship.class.isAssignableFrom(type);
schema.setProperty(urlProperty, url);
schema.setProperty(typeProperty, type.getSimpleName());
schema.setProperty(nameProperty, type.getSimpleName());
schema.setProperty(classNameProperty, type.getName());
schema.setProperty(extendsClassNameProperty, type.getSuperclass().getName());
schema.setProperty(isRelProperty, isRel);
schema.setProperty(flagsProperty, SecurityContext.getResourceFlags(rawType));
if (!isRel) {
final List<GraphObjectMap> relatedTo = new LinkedList<>();
final List<GraphObjectMap> relatedFrom = new LinkedList<>();
for (final PropertyKey key : config.getPropertySet(type, PropertyView.All)) {
if (key instanceof RelationProperty) {
final RelationProperty relationProperty = (RelationProperty) key;
final Relation relation = relationProperty.getRelation();
if (!relation.isHidden()) {
switch(relation.getDirectionForType(type)) {
case OUTGOING:
relatedTo.add(relationPropertyToMap(config, relationProperty));
break;
case INCOMING:
relatedFrom.add(relationPropertyToMap(config, relationProperty));
break;
case BOTH:
relatedTo.add(relationPropertyToMap(config, relationProperty));
relatedFrom.add(relationPropertyToMap(config, relationProperty));
break;
}
}
}
}
if (!relatedTo.isEmpty()) {
schema.setProperty(relatedToProperty, relatedTo);
}
if (!relatedFrom.isEmpty()) {
schema.setProperty(relatedFromProperty, relatedFrom);
}
}
}
}
return new Result(resultList, resultList.size(), false, false);
}
Aggregations