/**
* Copyright (C) 2010-2017 Structr GmbH
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Structr. If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.web.entity;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.structr.common.SecurityContext;
import org.structr.common.error.ErrorBuffer;
import org.structr.common.error.FrameworkException;
import org.structr.core.Export;
import org.structr.core.graph.ModificationEvent;
import org.structr.core.graph.ModificationQueue;
import org.structr.core.property.EndNodes;
import org.structr.core.property.Property;
import org.structr.core.property.PropertyMap;
import org.structr.dynamic.File;
import org.structr.web.entity.relation.MinificationSource;
/**
* Base class for minifiable files in structr
*
*/
public abstract class AbstractMinifiedFile extends File {
private static final Logger logger = LoggerFactory.getLogger(AbstractMinifiedFile.class.getName());
public static final Property<List<FileBase>> minificationSources = new EndNodes<>("minificationSources", MinificationSource.class);
@Override
public boolean onModification(final SecurityContext securityContext, final ErrorBuffer errorBuffer, final ModificationQueue modificationQueue) throws FrameworkException {
boolean shouldMinify = false;
final String myUUID = getUuid();
for (ModificationEvent modState : modificationQueue.getModificationEvents()) {
// only take changes on this exact file into account
if (myUUID.equals(modState.getUuid())) {
shouldMinify = shouldMinify || shouldModificationTriggerMinifcation(modState);
}
}
if (shouldMinify) {
try {
this.minify();
} catch (IOException ex) {
logger.warn("Could not automatically minify file", ex);
}
}
return super.onModification(securityContext, errorBuffer, modificationQueue);
}
@Export
public abstract void minify() throws FrameworkException, IOException;
public abstract boolean shouldModificationTriggerMinifcation(ModificationEvent modState);
public int getMaxPosition () {
int max = -1;
for (final MinificationSource neighbor : getOutgoingRelationships(MinificationSource.class)) {
max = Math.max(max, neighbor.getProperty(MinificationSource.position));
}
return max;
}
public String getConcatenatedSource () throws FrameworkException, IOException {
final StringBuilder concatenatedSource = new StringBuilder();
int cnt = 0;
for (MinificationSource rel : getSortedRelationships()) {
final FileBase src = rel.getTargetNode();
concatenatedSource.append(FileUtils.readFileToString(src.getFileOnDisk()));
// compact the relationships (if necessary)
if (rel.getProperty(MinificationSource.position) != cnt) {
rel.setProperties(securityContext, new PropertyMap(MinificationSource.position, cnt));
}
cnt++;
}
return concatenatedSource.toString();
}
public List<MinificationSource> getSortedRelationships() {
final List<MinificationSource> rels = new ArrayList();
getOutgoingRelationships(MinificationSource.class).forEach(rels::add);
Collections.sort(rels, (MinificationSource arg0, MinificationSource arg1) -> (arg0.getProperty(MinificationSource.position).compareTo(arg1.getProperty(MinificationSource.position))));
return rels;
}
/**
* Move a minification source to a new position.
* All minification sources between those positions have to be adjusted as well.
*
* @param from The position from where the minification source is moved
* @param to The position where to move the minification source
* @throws FrameworkException
*/
@Export
public void moveMinificationSource(final int from, final int to) throws FrameworkException {
for (MinificationSource rel : getOutgoingRelationships(MinificationSource.class)) {
int currentPosition = rel.getProperty(MinificationSource.position);
int change = 0;
if (from < to) {
change = -1;
} else if (from > to) {
change = 1;
}
if (currentPosition > from && currentPosition <= to) {
rel.setProperties(securityContext, new PropertyMap(MinificationSource.position, currentPosition + change));
} else if (currentPosition >= to && currentPosition < from) {
rel.setProperties(securityContext, new PropertyMap(MinificationSource.position, currentPosition + change));
} else if (currentPosition == from) {
rel.setProperties(securityContext, new PropertyMap(MinificationSource.position, to));
}
}
}
}