• [saiku] olap数据源管理


    一、应用场景

    系统初始化的时候
    如果没有创建olap数据源需要先创建olap数据源
    否则直接获取所有的数据源存放在全局变量datasources里面以便于后续步骤中获取plap-connections

    二、代码详细解析

    1、olap数据源对象结构

    (1) SaikuDatasource - org.saiku.datasources.datasource.SaikuDatasource

    public SaikuDatasource( String name, Type type, Properties properties ) {
        this.name = name;//数据源名称
        this.type = type;//数据源类型
        this.properties = properties;//数据源属性
    }
    public enum Type {
        OLAP
    }

    (2) DataSource - org.saiku.datasources.datasource.SaikuDatasource.DataSource

    public DataSource(SaikuDatasource datasource) {
        this.type = datasource.getType().toString();
        this.name = datasource.getName();
        this.driver = datasource.getProperties().getProperty("driver");
        this.location = datasource.getProperties().getProperty("location");
        this.username = datasource.getProperties().getProperty("username");
        this.password = datasource.getProperties().getProperty("password");
        this.id = datasource.getProperties().getProperty("id");
        this.encryptpassword =datasource.getProperties().getProperty("encrypt.password");
        this.securityenabled =datasource.getProperties().getProperty("security.enabled");
        this.securitytype = datasource.getProperties().getProperty("security.type");
        this.securitymapping =datasource.getProperties().getProperty("security.mapping");
        this.advanced = datasource.getProperties().getProperty("advanced");
    }

    2、新增OLAP数据源 

    (1)判断是否需要新增此OLAP数据源的代码如下:

        代码结构
        |-Database.loadLegacyDatasources()
            |- LegacyImporterImpl.importDatasources()
    详细代码LegacyImporterImpl.importDatasources()
    
        关键代码:
        
        1) 获取数据源配置文件所在文件夹
        
        String repoURL = "";
        FileSystemManager fileSystemManager = VFS.getManager();
        fileObject fileObject = fileSystemManager.resolveFile("res:saiku-datasources");
        repoURL = fileObject.getURL();
        
        2)遍历该文件夹下所有文件
        File[] files = new File(repoURL.getFile()).listFiles();
        
        3)获取OLAP数据源的配置构造saiku-ds对象并判断是否存在,不存在才添加
        for (File file : files) {
            
            Properties props = new Properties();
            props.load(new FileInputStream(file));
            
            稍微处理下props的location属性之后创建saikuDs
            SaikuDatasource ds = new SaikuDatasource(name, t, props);
            
            //获取已加入JCR的ds
            List<DataSource> dsList = irm.getAllDataSources();
            
            //比对待添加的OLAP_DS和已存在的OLAP_DS的名字,如果不存在,才添加
            boolean isExists = false;
                                
            for (DataSource dataSource : dsList) {
                if(dataSource.getName().equals(ds.getName())){
                    isExists = true;
                    break;
                }
            }
            
            if(!isExists){
                dsm.addDatasource(ds);                                    
            }
        }

     

    (2)新增数据源具体步骤

    第一步将ds加入JCR节点
    第二步将ds加入全局datasources
      RepositoryDatasourceManager.addDatasource(SaikuDatasource datasource)
      //源代码
      private Map<String, SaikuDatasource> datasources =
                Collections.synchronizedMap(new HashMap<String, SaikuDatasource>());
    IRepositoryManager irm
    = JackRabbitRepositoryManager.getJackRabbitRepositoryManager(configurationpath, datadir, repopassword,oldpassword); public SaikuDatasource addDatasource(SaikuDatasource datasource){ DataSource ds = new DataSource(datasource); irm.saveDataSource(ds, "/datasources/" + ds.getName() + ".sds", "fixme"); datasources.put(datasource.getName(), datasource); return datasource; }

    (3)详解第一步:将ds加入JCR节点

      JackRabbitRepositoryManager.saveDataSource(DataSource ds, String path, String user)
        
        //源代码
        public void saveDataSource(DataSource ds, String path, String user) throws RepositoryException {
        
        //定义字节输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        
        //将DataSource对象转换成XML文件,存入baos中
        try {
          JAXBContext jaxbContext = JAXBContext.newInstance(DataSource.class);
          Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
          jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
          jaxbMarshaller.marshal(ds, baos);
        } catch (JAXBException e) {
          log.error("Could not read XML", e);
        }
        
        //获取文件名
        int pos = path.lastIndexOf("/");
        String filename = "./" + path.substring(pos + 1, path.length());//结果为./schema名
        
        //获取数据源根节点/datadatasources
        Node n = getFolder(path.substring(0, pos));
        
        //在根节点下添加文件节点resNode: path = /datadatasources/filename
        //指定node名字为filename,类型为file,属性为olap_ds,以便后续查询olap数据源能查询到
        Node resNode = n.addNode(filename, "nt:file");
        resNode.addMixin("nt:olapdatasource");
    
        //在新创建的resNode节点下添加文件内容节点contentNode:
       //path = /datadatasources/filename/jcr:content
    //设置该内容节点的内容为转换的XML的内容 Node contentNode = resNode.addNode("jcr:content", "nt:resource"); contentNode.setProperty("jcr:data", baos.toString()); //至此,数据源属性节点和配置内容节点就加入到JCR结构中了 //最后,别忘了保存新增的节点 resNode.getSession().save(); }

    3、获取所有OLAP数据源

    (1) 初始化内容仓库管理器

    private String configurationXml = projectPath + "saiku-repository/configuration.xml";
    private String datadir = projectPath + "saiku-repository/data";    
    private String repopassword = "sa!kuanalyt!cs";
    private String oldpassword = "";
    
    IRepositoryManager irm = JackRabbitRepositoryManager.getJackRabbitRepositoryManager(configurationpath, datadir, repopassword,oldpassword);

    (2) 初始化JCR基本结构

    irm.start(userService);
        
        关键代码:
        
        1)获得内容根节点
        
        //根据configurationXml文件配置在datadir路径下创建JCR文件夹基本结构
        //相当于创建MyRepo
        RepositoryConfig config = RepositoryConfig.create(configurationXml, datadir);
        
        //根据JCR文件夹基本结构生成repository对象
        repository = RepositoryImpl.create(config);
        
        //获取操作JCR的权限[也叫Ticket]
        session = repository.login(
                  new SimpleCredentials("admin", password.toCharArray()));
        
        //根据session获取JCR的根节点
        JackrabbitSession js = (JackrabbitSession) session;
        session = js;
        root = session.getRootNode();
        root.getSession().save();
        
        2)为workspace注册Node的类型。四种类型:File/Folder/Schema/DataSource
        createFiles();
        createFolders();
        createSchemas();
        createDataSources();
        
        //创建的大致步骤
        NodeTypeManager manager = session.getWorkspace().getNodeTypeManager();//相同的代码
        NodeTypeTemplate ntt = manager.createNodeTypeTemplate();//相同的代码
        ntt.setName("nt:saikufiles");//依次nt:saikufiles/nt:saikufolders/nt:mondrianschema/nt:olapdatasource
        String[] str = new String[]{"nt:file"};//依次nt:saikufiles/nt:folder/nt:file/nt:file
        ntt.setDeclaredSuperTypeNames(str);
        ntt.setMixin(true);
        
        //创建pdt对象  name有几个值就创建几个
        //File           创建五个:name分别为owner/type/roles/users/jcr:data
        //Folder         创建四个:name分别为owner/type/roles/users
        //Schema         创建四个:name分别为owner/schemaname/cubenames/jcr:data
        ///DataSource    创建三个:name分别为owner/enabled/jcr:data
        PropertyDefinitionTemplate pdt = manager.createPropertyDefinitionTemplate();//相同的代码
        pdt.setName("owner");
        pdt.setRequiredType(PropertyType.STRING);//相同的代码
        
        ntt.getPropertyDefinitionTemplates().add(创建pdt对象);//有几个pdt就添加几次
        
        manager.registerNodeType(ntt, false);//注册新建的节点类型//相同的代码
        
        
        3)为workspace注册命名空间
        createNamespace();
        
        NamespaceRegistry ns = session.getWorkspace().getNamespaceRegistry();
        if (!Arrays.asList(ns.getPrefixes()).contains("home")) {
          ns.registerNamespace("home", "http://www.meteorite.bi/namespaces/home");
        }
        
        4)构建repository结构
        
        在root节点下新增如下文件夹节点结构,并赋予一定的ACL权限<略>
        
      结构:
    /homes /datasources /etc /etc/legacyreports /etc/theme /etc/theme/legacyreports Node n = JcrUtils.getOrAddFolder(root, "homes"); n.addMixin("nt:saikufolders"); n = JcrUtils.getOrAddFolder(root, "datasources"); n.addMixin("nt:saikufolders"); n = JcrUtils.getOrAddFolder(root, "etc"); n.addMixin("nt:saikufolders"); n = JcrUtils.getOrAddFolder(n, "legacyreports"); n.addMixin("nt:saikufolders"); n = JcrUtils.getOrAddFolder(root, "etc/theme"); n.addMixin("nt:saikufolders"); n = JcrUtils.getOrAddFolder(n, "legacyreports"); n.addMixin("nt:saikufolders"); session.save();

    (3) 获取JCR结构中存在的数据源

    List<DataSource> dslist = irm.getAllDataSources();
        
        关键代码:
        
        1)获取MDX查询管理器
        QueryManager qm = session.getWorkspace().getQueryManager();
        
        2)查询执行属性的数据,获得所有类型为Cube数据源的节点
        
        //创建Cube数据源时dsNode.addMixin("nt:olapdatasource");
        String sql = "SELECT * FROM [nt:olapdatasource]";
        Query query = qm.createQuery(sql, Query.JCR_SQL2);
        QueryResult res = query.execute();
        NodeIterator node = res.getNodes();
        
        3)遍历NodeIterator,解析获取每一个node的属性构造Datasource对象
        Node n = node.nextNode();//结果为:node_path = /datadatasources/filename
        
        4)获取cube数据源的schema配置
        String schemaContent = n.getNodes("jcr:content").nextNode().getProperty("jcr:data").getString();
        
        5)将XML文件内容数据流转换为DataSource对象
        Unmarshaller jaxbMarshaller = jaxbContext != null ? jaxbContext.createUnmarshaller() : null;
        JAXBContext jaxbContext = JAXBContext.newInstance(DataSource.class);
        InputStream stream = new ByteArrayInputStream(schemaContent.getBytes());
        DataSource d = (DataSource) (jaxbMarshaller != null ? jaxbMarshaller.unmarshal(stream) : null);
        
        6)设置数据源的路径
        d.setPath(n.getPath());
        
        7)遍历完所有olapds_node以后,返回dsList

    (4) 根据dsList拼凑saikuDsList

        for (DataSource file : dslist) {
            Properties props = new Properties();
            根据file构建props
            SaikuDatasource.Type t = SaikuDatasource.Type.valueOf(file.getType().toUpperCase());//OLAP
            SaikuDatasource ds = new SaikuDatasource(file.getName(),t,props);
            datasources.put(file.getName(), ds);//将saikuDs加入到全局变量datasources中
        }
  • 相关阅读:
    软件开的目录规范+sys,os,time模块
    模块与包
    匿名函数+函数递归+二分法+面向过程编程
    快捷键
    补充叠加多个装饰器:加载顺序与执行顺序+迭代器+自定义迭代器的方式:生成器+三元表达式
    闭包函数的应用+内置函数
    函数对象+函数嵌套+名称空间与作用域+闭包函数
    SP15637 Mr Youngs Picture Permutations 高维动态规划
    LG3825/BZOJ4945/LOJ2305 「NOI2017」游戏 dfs+2-SAT
    LG1198/BZOJ1012 「JSOI2008」最大数 线段树+离线
  • 原文地址:https://www.cnblogs.com/avivaye/p/4898287.html
Copyright © 2020-2023  润新知