org.apache.openmeetings.backup.converter.WbConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.openmeetings.backup.converter.WbConverter.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.openmeetings.backup.converter;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.UUID.randomUUID;
import static org.apache.commons.lang3.math.NumberUtils.toLong;
import static org.apache.openmeetings.db.dto.room.Whiteboard.ATTR_FILE_ID;
import static org.apache.openmeetings.db.dto.room.Whiteboard.ATTR_FILE_TYPE;
import static org.apache.openmeetings.db.dto.room.Whiteboard.ATTR_SLIDE;
import static org.apache.openmeetings.db.dto.room.Whiteboard.ATTR_TYPE;
import static org.apache.openmeetings.util.OmFileHelper.EXTENSION_WML;
import static org.apache.openmeetings.util.OpenmeetingsVariables.PARAM__SRC;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.openmeetings.db.dto.room.Whiteboard;
import org.apache.openmeetings.db.entity.file.BaseFileItem;
import org.apache.openmeetings.db.entity.file.FileItem;
import org.apache.openmeetings.util.OmFileHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.openjson.JSONArray;
import com.github.openjson.JSONObject;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.security.NoTypePermission;
import com.thoughtworks.xstream.security.NullPermission;
import com.thoughtworks.xstream.security.PrimitiveTypePermission;

public class WbConverter {
    private static final Logger log = LoggerFactory.getLogger(WbConverter.class);
    private static final String ATTR_STROKE = "strokeWidth";
    private static final String ATTR_OPACITY = "opacity";
    private static final String TYPE_IMAGE = "image";

    private WbConverter() {
        //should not be used
    }

    private static String getColor(int val) {
        return String.format("#%06X", 0xFFFFFF & val);
    }

    private static void add(Whiteboard wb, JSONObject o) {
        String uid = randomUUID().toString();
        wb.put(uid, o.put("uid", uid));
    }

    private static JSONObject init(Whiteboard wb, List<?> props) {
        return init(wb, props, true);
    }

    private static JSONObject init(Whiteboard wb, List<?> props, boolean addDim) {
        double left = ((Number) props.get(props.size() - 5)).doubleValue();
        double top = ((Number) props.get(props.size() - 4)).doubleValue();
        double w = ((Number) props.get(props.size() - 3)).doubleValue();
        double h = ((Number) props.get(props.size() - 2)).doubleValue();
        JSONObject o = new JSONObject().put(ATTR_SLIDE, 0);
        if (addDim) {
            o.put("left", left).put("top", top).put("width", w).put("height", h);
            wb.setWidth((int) Math.max(wb.getWidth(), w + left));
            wb.setHeight((int) Math.max(wb.getHeight(), h + top));
        }
        return o;
    }

    private static JSONObject setColor(JSONObject o, String stroke, String fill) {
        return o.put("stroke", stroke).put("fill", fill);
    }

    private static void processText(Whiteboard wb, List<?> props) {
        if (props.size() < 12) {
            return;
        }
        String color = getColor(getInt(props, 2));
        String style = (String) props.get(4);
        JSONObject o = setColor(init(wb, props), color, color).put(ATTR_TYPE, "i-text").put("text", props.get(1))
                .put("fontSize", props.get(3));
        if (style.indexOf("bold") > -1) {
            o.put("fontWeight", "bold");
        }
        if (style.indexOf("italic") > -1) {
            o.put("fontStyle", "inalic");
        }
        add(wb, o);
    }

    private static void processPath(Whiteboard wb, List<?> props) {
        if (props.size() < 13) {
            return;
        }
        String color = getColor(getInt(props, 4));
        JSONObject o = setColor(init(wb, props), color, null).put(ATTR_TYPE, "path").put(ATTR_STROKE, props.get(3));
        @SuppressWarnings("unchecked")
        List<List<?>> points = (List<List<?>>) props.get(1);
        JSONArray path = new JSONArray();
        for (List<?> point : points) {
            if (path.length() == 0) {
                path.put(new JSONArray(Arrays.asList("M", getInt(point, 1), getInt(point, 2))));
            } else if (path.length() == points.size() - 1) {
                path.put(new JSONArray(Arrays.asList("L", getInt(point, 3), getInt(point, 4))));
            } else {
                path.put(new JSONArray(Arrays.asList("Q", getInt(point, 1), getInt(point, 2), getInt(point, 3),
                        getInt(point, 4))));
            }
        }
        add(wb, o.put("path", path).put(ATTR_OPACITY, props.get(5)));
    }

    private static void processLine(Whiteboard wb, List<?> props) {
        if (props.size() < 16) {
            return;
        }
        String color = getColor(getInt(props, 1));
        add(wb, setColor(init(wb, props), color, color).put(ATTR_TYPE, "line").put(ATTR_STROKE, props.get(2))
                .put(ATTR_OPACITY, props.get(3)).put("x1", props.get(4)).put("y1", props.get(5))
                .put("x2", props.get(6)).put("y2", props.get(7)));
    }

    private static int getInt(List<?> props, int idx) {
        Object o = props.get(idx);
        if (o instanceof Number) {
            return ((Number) o).intValue();
        } else if (o instanceof String) {
            return NumberUtils.toInt((String) o);
        }
        return 0;
    }

    private static JSONObject processRect(Whiteboard wb, List<?> props) {
        if (props.size() < 15) {
            return null;
        }
        return setColor(init(wb, props), 1 == getInt(props, 4) ? getColor(getInt(props, 1)) : null,
                1 == getInt(props, 5) ? getColor(getInt(props, 3)) : null).put(ATTR_TYPE, "rect")
                        .put(ATTR_STROKE, props.get(2)).put(ATTR_OPACITY, props.get(6));
    }

    private static void processEllipse(Whiteboard wb, List<?> props) {
        JSONObject o = processRect(wb, props);
        if (o != null) {
            o.put(ATTR_TYPE, "ellipse").put("rx", o.getDouble("width") / 2).put("ry", o.getDouble("height") / 2);
            add(wb, o);
        }
    }

    private static void processClipart(Whiteboard wb, List<?> props) {
        if (props.size() < 19) {
            return;
        }
        String src = (String) props.get(2);
        int idx = src.indexOf("cliparts");
        if (idx > -1) {
            src = String.format("./public/%s", src.substring(idx));
        }
        add(wb, init(wb, props).put(ATTR_TYPE, TYPE_IMAGE).put("omType", "Clipart").put(PARAM__SRC, src)
                .put("angle", props.get(3)));
    }

    private static long getFileId(String src) {
        int idx1 = src.lastIndexOf('/'), idx2 = src.indexOf('?');
        if (idx1 < 0 || idx2 < 0) {
            return -1;
        }
        return toLong(src.substring(idx1 + 1, idx2), -1);
    }

    // will support only import from 3.2.x+
    private static void processImage(Whiteboard wb, List<?> props) {
        if (props.size() < 17) {
            return;
        }
        long fileId = getFileId((String) props.get(2));
        if (fileId < 0) {
            return;
        }
        add(wb, init(wb, props).put(ATTR_TYPE, TYPE_IMAGE).put(ATTR_FILE_TYPE, BaseFileItem.Type.Image.name())
                .put(ATTR_FILE_ID, fileId));
    }

    private static void processDoc(Whiteboard wb, List<?> props) {
        if (props.size() < 27) {
            return;
        }
        long fileId = getFileId((String) props.get(2));
        if (fileId < 0) {
            return;
        }
        add(wb, init(wb, props, false).put(ATTR_TYPE, TYPE_IMAGE)
                .put(ATTR_FILE_TYPE, BaseFileItem.Type.Presentation.name()).put(ATTR_FILE_ID, fileId));
    }

    private static void processVid(Whiteboard wb, List<?> props) {
        if (props.size() < 14) {
            return;
        }
        add(wb, init(wb, props).put(ATTR_TYPE, TYPE_IMAGE).put(ATTR_FILE_TYPE, BaseFileItem.Type.Video.name())
                .put(ATTR_FILE_ID, props.get(1)));
    }

    public static Whiteboard convert(FileItem fi) {
        Whiteboard wb = new Whiteboard();
        wb.setWidth(0);
        wb.setHeight(0);
        Set<String> uids = new HashSet<>();
        List<?> wml = loadWmlFile(fi.getHash());
        for (Object wo : wml) {
            List<?> props = (List<?>) wo;
            if (!props.isEmpty()) {
                String uid = (String) props.get(props.size() - 1);
                if (uids.contains(uid)) {
                    continue;
                }
                uids.add(uid);
                switch ((String) props.get(0)) {
                case "letter":
                    processText(wb, props);
                    break;
                case "paint":
                    processPath(wb, props);
                    break;
                case "line":
                case "uline":
                    processLine(wb, props);
                    break;
                case "rectangle":
                case "drawarrow": // will replace with rectangle
                    add(wb, processRect(wb, props));
                    break;
                case "ellipse":
                    processEllipse(wb, props);
                    break;
                case "clipart":
                    processClipart(wb, props);
                    break;
                case TYPE_IMAGE:
                    processImage(wb, props);
                    break;
                case "swf":
                    processDoc(wb, props);
                    break;
                case "flv":
                    processVid(wb, props);
                    break;
                }
            }
        }
        return wb;
    }

    public static List<?> loadWmlFile(String hash) {
        String name = OmFileHelper.getName(hash, EXTENSION_WML);
        File file = new File(OmFileHelper.getUploadWmlDir(), name);
        log.debug("filepathComplete: {}", file);

        XStream xstream = new XStream(new XppDriver());
        xstream.setMode(XStream.NO_REFERENCES);
        xstream.addPermission(NoTypePermission.NONE);
        xstream.addPermission(NullPermission.NULL);
        xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
        xstream.allowTypeHierarchy(List.class);
        xstream.allowTypeHierarchy(String.class);
        try (InputStream is = new FileInputStream(file);
                BufferedReader reader = new BufferedReader(new InputStreamReader(is, UTF_8))) {
            return (List<?>) xstream.fromXML(reader);
        } catch (Exception err) {
            log.error("loadWmlFile", err);
        }
        return new ArrayList<>();
    }
}