/*
* Copyright 2011 Uwe Krueger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mandelsoft.mand.tools;
import com.mandelsoft.mand.IllegalConfigurationException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.mandelsoft.mand.Environment;
import com.mandelsoft.io.AbstractFile;
import com.mandelsoft.mand.MandelData;
import com.mandelsoft.mand.MandelFileName;
import com.mandelsoft.mand.MandelHeader;
import com.mandelsoft.mand.MandelName;
import com.mandelsoft.mand.QualifiedMandelName;
import com.mandelsoft.mand.Settings;
import com.mandelsoft.mand.scan.ElementHandle;
import com.mandelsoft.mand.scan.MandelFolderCache;
import com.mandelsoft.mand.scan.MandelFolder;
import com.mandelsoft.mand.scan.MandelHandle;
import com.mandelsoft.mand.scan.MandelScanner;
import com.mandelsoft.mand.scan.MandelScannerUtils;
import com.mandelsoft.mand.util.MandUtils;
import com.mandelsoft.util.Utils;
/**
*
* @author Uwe Krüger
*/
public class Copy<E extends ExecutionHandler> extends Command {
static protected byte[] buffer=new byte[1024];
protected int count=0;
protected E exec;
/////////////////////////////////////////////////////////////////////
// Execution Handler
/////////////////////////////////////////////////////////////////////
public class VerboseHandler implements ExecutionHandler {
public void copy(ElementHandle src, AbstractFile dst)
{
System.out.println("copying "+src.getFile()+" to "+dst.getFile());
}
public void backupInfoFile(AbstractFile mf)
{
System.out.println("backup request "+mf);
}
public void backupRasterFile(AbstractFile mf)
{
System.out.println("backup raster "+mf);
}
public void backupAreaColormapFile(AbstractFile mf)
{
System.out.println("backup area colormap "+mf);
}
public void finish()
{
}
}
/////////////////////////////////////////////////////////////////////
public class DefaultHandler extends Copy.VerboseHandler {
protected Set<File> destinations=new HashSet<File>();
public void addDestination(File d)
{
if (!destinations.contains(d)) {
destinations.add(d);
}
}
@Override
public void copy(ElementHandle src, AbstractFile dst)
{
int n;
File d=dst.getFile();
AbstractFile s=src.getFile();
if (d==null) {
System.out.println("copy to URL not possible: "+dst);
return;
}
super.copy(src,dst);
addDestination(d.getParentFile());
try {
BufferedInputStream is=new BufferedInputStream(s.getInputStream());
try {
BufferedOutputStream os=new BufferedOutputStream(new FileOutputStream(
d));
try {
while ((n=is.read(buffer))>0) {
os.write(buffer, 0, n);
}
}
finally {
os.close();
}
d.setLastModified(s.getLastModified());
}
finally {
is.close();
}
}
catch (IOException io) {
System.out.println("cannot copy "+s+": "+io);
io.printStackTrace(System.err);
}
}
@Override
public void backupInfoFile(AbstractFile mf)
{
super.backupInfoFile(mf);
Copy.this.dst.backupInfoFile(mf);
}
@Override
public void backupRasterFile(AbstractFile mf)
{
super.backupRasterFile(mf);
Copy.this.dst.backupRasterFile(mf);
}
@Override
public void backupAreaColormapFile(AbstractFile mf)
{
super.backupAreaColormapFile(mf);
Copy.this.dst.backupAreaColormapFile(mf);
}
public void updateCaches()
{
for (File f :destinations) {
System.out.println("checking cache "+f);
if (MandelFolderCache.isCached(f)) {
try {
System.out.println("updating cache in "+f);
MandelFolder mf=new MandelFolder(f);
mf.recreate();
}
catch (IOException io) {
System.out.println(" cannot recreate cache for "+f);
}
}
}
}
@Override
public void finish()
{
updateCaches();
}
}
//////////////////////////////////////////////////////////////////////
// exits for file type handler
//////////////////////////////////////////////////////////////////////
protected boolean handleFile(FileType ft, ElementHandle h)
{
return ft.handle(h);
}
protected String map(AbstractFile s)
{
MandelFileName n=MandelFileName.create(s);
MandelName sn=n.getName();
String eff=sn.getEffective();
if (!eff.startsWith(sp)) return null;
eff=dp+eff.substring(sp.length());
MandelName dn=MandelName.create(eff);
String fn=n.get(dn,true).getFileName();
return fn;
}
/////////////////////////////////////////////////////////////////////
// File Type Handler
/////////////////////////////////////////////////////////////////////
protected abstract class FileType {
private String name;
private Map<AbstractFile,AbstractFile> pathmapping=new HashMap<AbstractFile,AbstractFile>();
private AbstractFile def;
private MandelScanner.Filter filter;
protected MandelScanner srcscan;
protected MandelScanner dstscan;
FileType(String name, MandelScanner.Filter filter,
MandelScanner srcscan, MandelScanner dstscan)
{
this.name=name;
this.filter=filter;
this.srcscan=srcscan;
this.dstscan=dstscan;
}
public boolean match(MandelHeader h)
{
return filter.filter(h);
}
public boolean match(ElementHandle<?> h)
{
return match(h.getHeader());
}
protected void handlePath(String prop)
{
String d=dst.getProperty(prop);
if (!Utils.isEmpty(d)) {
AbstractFile fd=dst.createMandelFile(d);
if (src!=null) {
String s=src.getProperty(prop);
if (!Utils.isEmpty(s)) {
AbstractFile fs=src.createMandelFile(s);
pathmapping.put(fs, fd);
}
}
def=fd;
}
}
public String getName()
{
return name;
}
public void execute()
{ boolean v;
System.out.println("copying "+getName()+"...");
for (ElementHandle<?> h:srcscan.getAllHandles()) {
if (match(h)) {
//System.out.println(" found "+h.getName()+" DOIT "+h.getHeader());
handleFile(this,h);
}
}
}
protected boolean handle(ElementHandle<?> h)
{
AbstractFile mf=h.getFile();
AbstractFile p=mf.getParent();
AbstractFile d=pathmapping.get(p);
if (d==null) d=def;
if (d==null) {
System.out.println("no target for "+mf);
return false;
}
else {
String fn=map(mf);
if (fn==null) return false;
exec.copy(h, d.getSub(fn));
cleanup(h);
count++;
return true;
}
}
public void cleanup(ElementHandle<?> h)
{
}
protected boolean has(ElementHandle<?> h)
{
MandelHandle mh=((MandelHandle)h);
Set<MandelHandle> set=dstscan.getMandelHandles(mh.getName());
for (MandelHandle dh:set) {
if (match(dh)) return true;
}
return false;
}
protected boolean use(ElementHandle<?> h)
{
return use((MandelHandle)h,dst.getImageDataScanner());
// MandelHandle mh=((MandelHandle)h);
// return dst.getImageDataScanner().getMandelHandles(mh.getName()).isEmpty();
}
protected boolean use(MandelHandle mh, MandelScanner ds)
{
Set<MandelHandle> set=ds.getMandelHandles(mh.getName());
if (set.isEmpty()) return true;
long lm=mh.getFile().getLastModified();
for (MandelHandle dh:set) {
if (dh.getFile().getLastModified()>=lm) return false;
}
return true;
}
}
/////////////////////////////////////////////////////////////////////
protected class InfoType extends FileType {
InfoType()
{
super("requests", MandelScanner.INFO,
src==null?null:src.getInfoScanner(), dst.getInfoScanner());
handlePath(Settings.INFO_SAVE_PATH);
}
}
protected class AreaColmapType extends FileType {
AreaColmapType()
{
super("areacolmaps", MandelScanner.AREACOLMAP,
src==null?null:src.getAreaColormapScanner(), dst.getAreaColormapScanner());
handlePath(Settings.AREACOLMAP_PATH);
handlePath(Settings.AREACOLMAP_SAVE_PATH);
}
@Override
protected boolean use(ElementHandle h)
{
return use((MandelHandle)h,dst.getAreaColormapScanner());
}
}
/////////////////////////////////////////////////////////////////////
protected class RasterType extends FileType {
RasterType()
{
super("rasters", MandelScanner.RASTER,
src==null?null:src.getRasterScanner(), dst.getRasterScanner());
handlePath(Settings.VARIANT_SEEN_PATH);
handlePath(Settings.VARIANT_SAVE_PATH);
handlePath(Settings.RASTER_SEEN_PATH);
handlePath(Settings.RASTER_SAVE_PATH);
}
@Override
public void cleanup(ElementHandle h)
{
QualifiedMandelName mn=((MandelHandle)h).getName();
Set<MandelHandle> set=dst.getInfoScanner().getMandelHandles(mn);
for (MandelHandle mh:set) {
System.out.println(" backup request "+mh.getFile());
exec.backupInfoFile(mh.getFile());
}
}
}
/////////////////////////////////////////////////////////////////////
protected class RasterImageType extends FileType {
RasterImageType()
{
super("raster images", MandelScanner.RASTERIMAGE,
src==null?null:src.getRasterImageScanner(), dst.getRasterImageScanner());
handlePath(Settings.VARIANT_SEEN_PATH);
handlePath(Settings.VARIANT_SAVE_PATH);
handlePath(Settings.RASTERIMAGE_SAVE_PATH);
}
@Override
protected boolean use(ElementHandle h)
{
return use((MandelHandle)h,dst.getRasterImageScanner());
// MandelHandle mh=((MandelHandle)h);
// return dst.getRasterImageScanner().
// getMandelHandles(mh.getName()).isEmpty();
}
@Override
public void cleanup(ElementHandle h)
{
MandelHandle mh=((MandelHandle)h);
QualifiedMandelName mn=mh.getName();
for (MandelHandle m:dst.getInfoScanner().getMandelHandles(mn)) {
System.out.println(" backup request "+m.getFile());
dst.backupInfoFile(m.getFile());
}
for (MandelHandle m:dst.getRasterScanner().getMandelHandles(mn)) {
System.out.println(" backup raster "+m.getFile());
exec.backupRasterFile(m.getFile());
}
for (MandelHandle m:dst.getAreaColormapScanner().getMandelHandles(mn)) {
System.out.println(" backup area colormap "+m.getFile());
exec.backupAreaColormapFile(m.getFile());
}
}
}
/////////////////////////////////////////////////////////////////////
// class
/////////////////////////////////////////////////////////////////////
protected Environment src;
protected Environment dst;
protected List<FileType> types=new ArrayList<FileType>();
protected String sp;
protected String dp;
public Copy(Environment src, Environment dst)
{
this.src=src;
this.dst=dst;
this.types.add(new InfoType());
this.types.add(new AreaColmapType());
this.types.add(new RasterType());
this.types.add(new RasterImageType());
}
protected void additionalSteps()
{
}
protected void execute()
{
for (FileType t:types) {
t.execute();
}
additionalSteps();
exec.finish();
}
///////////////////////////////////////////////////////////////////////////
public void copy(MandelName s, MandelName d)
{
if (s.isLocalName() || d.isRemoteName()) {
throw new IllegalArgumentException("remote name not supported");
}
sp=s.getEffective();
dp=d.getEffective();
execute();
}
public void setExecutionHandler(E h)
{
exec=h;
}
///////////////////////////////////////////////////////////////////////////
public static void main(String[] args)
{ try {
int c=0;
boolean vflag=false;
File src=new File("F://Mandel2");
File dst=new File("F://Mandel");
String sn=null;
String dn=null;
while (args.length>c&&args[c].charAt(0)=='-') {
for (int i=1; i<args[c].length();
i++) {
char opt;
switch (opt=args[c].charAt(i)) {
case 'v':
vflag=true;
break;
default:
Error("illegal option '"+opt+"'");
}
}
c++;
}
if (args.length>c) src=new File(args[c++]);
if (args.length>c) dst=new File(args[c++]);
if (args.length>c) sn=args[c++];
else Error("copy: [-v] <srcroot> <dstroot> <srcname>");
System.out.println("copying from "+src+" to "+dst);
if (!src.isDirectory()) Error(src+" is no directory");
if (!dst.isDirectory()) Error(dst+" is no directory");
Environment env_src=new Environment("mandtool", null, src);
Environment env_dst=new Environment("mandtool", null, dst);
MandelName s=MandelName.create(sn);
MandelData sd=MandelScannerUtils.getMandelInfo(env_src.getAllScanner(), s);
if (sd==null) Error("source area not found");
MandelName n=MandUtils.lookupRoot(env_dst.getAllScanner(), sd.getInfo());
MandelData dd=MandelScannerUtils.getMandelInfo(env_dst.getAllScanner(), n);
if (dd.getInfo().isSameArea(sd.getInfo())) Error("already there");
n=MandUtils.getNextSubName(n, env_dst.getAllScanner());
System.out.println("target area: "+n);
Copy<ExecutionHandler> a=new Copy<ExecutionHandler>(env_src, env_dst);
if (vflag) {
a.setExecutionHandler(a.new VerboseHandler());
}
else {
a.setExecutionHandler(a.new DefaultHandler());
}
a.copy(s, n);
System.out.println(""+a.count+" copied");
}
catch (IllegalConfigurationException ex) {
Command.Error("illegal config: "+ex);
}
}
}