net.sf.farrago.namespace.sfdc.SfdcNameDirectory.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.farrago.namespace.sfdc.SfdcNameDirectory.java

Source

/*
// Licensed to DynamoBI Corporation (DynamoBI) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  DynamoBI 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 net.sf.farrago.namespace.sfdc;

import com.sforce.soap.partner.*;

import java.io.StringWriter;

import java.rmi.RemoteException;

import java.sql.*;

import java.util.*;
import java.util.regex.Pattern;

import net.sf.farrago.namespace.*;
import net.sf.farrago.namespace.impl.*;
import net.sf.farrago.namespace.sfdc.resource.*;
import net.sf.farrago.type.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.eigenbase.reltype.RelDataType;
import org.eigenbase.sql.type.SqlTypeName;

/**
 * SfdcNameDirectory provides an implementation of the {@link
 * FarragoMedNameDirectory} interface.
 *
 * @author Sunny Choi
 * @version $Id$
 */
class SfdcNameDirectory extends MedAbstractNameDirectory {
    //~ Static fields/initializers ---------------------------------------------

    private static final Properties EMPTY_PROPERTIES = new Properties();
    protected static final int MAX_PRECISION = 256;

    protected static final Log log = LogFactory.getLog(SfdcNameDirectory.class);

    //~ Instance fields --------------------------------------------------------

    // ~ Instance fields -------------------------------------------------------

    final SfdcDataServer server;
    String scope;
    int varcharPrecision;
    private final Map<String, Pattern> patternMap;

    //~ Constructors -----------------------------------------------------------

    // ~ Constructors ----------------------------------------------------------

    SfdcNameDirectory(SfdcDataServer server, String scope) {
        this.server = server;
        this.scope = scope;
        this.varcharPrecision = this.server.getVarcharPrecision();
        this.patternMap = new HashMap<String, Pattern>();
    }

    //~ Methods ----------------------------------------------------------------

    // ~ Methods ---------------------------------------------------------------

    // implement FarragoMedNameDirectory
    public FarragoMedColumnSet lookupColumnSet(FarragoTypeFactory typeFactory, String foreignName,
            String[] localName) throws SQLException {
        if (!scope.equals(FarragoMedMetadataQuery.OTN_TABLE)) {
            return null;
        }

        return server.newColumnSet(localName, server.getProperties(), typeFactory, null, Collections.EMPTY_MAP);
    }

    // implement FarragoMedNameDirectory
    public FarragoMedNameDirectory lookupSubdirectory(String foreignName) throws SQLException {
        if (scope.equals(FarragoMedMetadataQuery.OTN_SCHEMA)) {
            if (!foreignName.equals("SFDC") && !foreignName.equals("DEFAULT")) {
                return null;
            }
            return new SfdcNameDirectory(server, FarragoMedMetadataQuery.OTN_TABLE);
        }
        return null;
    }

    // implement FarragoMedNameDirectory
    public boolean queryMetadata(FarragoMedMetadataQuery query, FarragoMedMetadataSink sink) throws SQLException {
        if (scope.equals(FarragoMedMetadataQuery.OTN_SCHEMA)) {
            boolean wantSchemas = query.getResultObjectTypes().contains(FarragoMedMetadataQuery.OTN_SCHEMA);
            if (wantSchemas) {
                sink.writeObjectDescriptor("SFDC", FarragoMedMetadataQuery.OTN_SCHEMA, null, EMPTY_PROPERTIES);
            }
        } else {
            boolean wantTables = query.getResultObjectTypes().contains(FarragoMedMetadataQuery.OTN_TABLE);
            if (wantTables) {
                if (!queryTables(query, sink)) {
                    return false;
                }
            }
            boolean wantColumns = query.getResultObjectTypes().contains(FarragoMedMetadataQuery.OTN_COLUMN);
            if (wantColumns) {
                if (!queryColumns(query, sink)) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean queryTables(FarragoMedMetadataQuery query, FarragoMedMetadataSink sink) throws SQLException {
        try {
            DescribeGlobalResult describeGlobalResult = server.getEntityTypes();
            if (!(describeGlobalResult == null)) {
                DescribeGlobalSObjectResult[] types = describeGlobalResult.getSobjects();
                if (!(types == null)) {
                    for (int i = 0; i < types.length; i++) {
                        String tableName = types[i].getName();
                        if (isIncluded(tableName, query)) {
                            sink.writeObjectDescriptor(tableName, FarragoMedMetadataQuery.OTN_TABLE, null,
                                    EMPTY_PROPERTIES);
                        }
                        if (isLovIncluded(tableName, query)) {
                            sink.writeObjectDescriptor(tableName + "_LOV", FarragoMedMetadataQuery.OTN_TABLE, null,
                                    EMPTY_PROPERTIES);
                        }
                    }
                }
            }
        } catch (RemoteException re) {
            throw SfdcResource.instance().BindingCallException.ex(re.getMessage());
        }
        return true;
    }

    private boolean queryColumns(FarragoMedMetadataQuery query, FarragoMedMetadataSink sink) throws SQLException {
        try {
            DescribeGlobalResult describeGlobalResult = server.getEntityTypes();
            if (!(describeGlobalResult == null)) {
                // Get the array of object names
                DescribeGlobalSObjectResult[] types = describeGlobalResult.getSobjects();
                for (int i = 0; i < types.length; i++) {
                    if (!isIncluded(types[i].getName(), query) && !isLovIncluded(types[i].getName(), query)) {
                        continue;
                    }

                    // verify can access objects
                    DescribeSObjectResult describeSObjectResult = (DescribeSObjectResult) server
                            .getEntityDescribe(types[i].getName());

                    // check the name
                    if ((describeSObjectResult != null)
                            && describeSObjectResult.getName().equals(types[i].getName())) {
                        if (isIncluded(types[i].getName(), query)) {
                            com.sforce.soap.partner.Field[] fields = describeSObjectResult.getFields();
                            int ordinal = 0;
                            for (int j = 0; j < fields.length; j++) {
                                RelDataType reltype = toRelType(fields[j], sink.getTypeFactory());
                                sink.writeColumnDescriptor(types[i].getName(), fields[j].getName(), ordinal,
                                        reltype, null, null, EMPTY_PROPERTIES);
                                ordinal++;
                            }
                        }
                        if (isLovIncluded(types[i].getName(), query)) {
                            // import picklist LOV as well
                            RelDataType reltype = sink.getTypeFactory()
                                    .createTypeWithNullability(sink.getTypeFactory()
                                            .createSqlType(SqlTypeName.VARCHAR, 25 + this.varcharPrecision), true);
                            sink.writeColumnDescriptor(types[i].getName() + "_LOV", "Field", 0, reltype, null, null,
                                    EMPTY_PROPERTIES);
                            reltype = sink.getTypeFactory().createTypeWithNullability(sink.getTypeFactory()
                                    .createSqlType(SqlTypeName.VARCHAR, MAX_PRECISION + this.varcharPrecision),
                                    true);
                            sink.writeColumnDescriptor(types[i].getName() + "_LOV", "Value", 1, reltype, null, null,
                                    EMPTY_PROPERTIES);
                        }
                    } else {
                        if (types[i].getName().endsWith("__c")) {
                            log.info(SfdcResource.instance().ObjectExtractErrorMsg.str(types[i].getName()));
                        } else {
                            throw SfdcResource.instance().InvalidObjectException.ex(types[i].getName());
                        }
                    }
                }
            }
        } catch (RemoteException re) {
            throw SfdcResource.instance().BindingCallException.ex(re.getMessage());
        }
        return true;
    }

    private boolean isIncluded(String tableName, FarragoMedMetadataQuery query) {
        FarragoMedMetadataFilter filter = (FarragoMedMetadataFilter) query.getFilterMap()
                .get(FarragoMedMetadataQuery.OTN_TABLE);
        if (filter == null) {
            return true;
        }
        boolean included = false;
        if (filter.getRoster() != null) {
            if (filter.getRoster().contains(tableName)) {
                included = true;
            }
        } else {
            Pattern pattern = getPattern(filter.getPattern());
            included = pattern.matcher(tableName).matches();
        }
        if (filter.isExclusion()) {
            included = !included;
        }
        return included;
    }

    private boolean isLovIncluded(String tableName, FarragoMedMetadataQuery query) {
        return isIncluded(tableName + "_LOV", query);
    }

    // See: MedAbstractMetadataSink.getPattern()
    Pattern getPattern(String likePattern) {
        Pattern pattern = patternMap.get(likePattern);
        if (pattern == null) {
            StringWriter regex = new StringWriter();
            int n = likePattern.length();
            for (int i = 0; i < n; ++i) {
                char c = likePattern.charAt(i);
                switch (c) {
                case '%':
                    regex.write(".*");
                    break;
                case '_':
                    regex.write(".");
                    break;
                default:
                    regex.write((int) c);
                    break;
                }
            }
            pattern = Pattern.compile(regex.toString());
            patternMap.put(likePattern, pattern);
        }
        return pattern;
    }

    protected RelDataType toRelType(Field field, FarragoTypeFactory typeFactory) {
        SqlTypeName typeName = convertSfdcSqlToSqlType(field.getType());
        if (typeName.allowsPrec()) {
            if (typeName.allowsScale()) { // only decimal type
                int maxPrecision = SqlTypeName.DECIMAL.MAX_NUMERIC_PRECISION;
                int precision = field.getPrecision();
                int scale = field.getScale();
                if ((precision > maxPrecision) || (scale > precision)) {
                    precision = maxPrecision;
                    int cappedScale = 6;
                    if (scale > cappedScale) {
                        scale = cappedScale;
                    }
                }
                if (scale < 0) {
                    scale = 0;
                }
                return typeFactory.createTypeWithNullability(typeFactory.createSqlType(typeName, precision, scale),
                        true);
            } else {
                int precision = field.getPrecision();
                String fieldType = field.getType().getValue().toLowerCase();
                if (typeName.equals(SqlTypeName.TIMESTAMP) || typeName.equals(SqlTypeName.TIME)) {
                    precision = typeName.getDefaultPrecision();
                } else if (fieldType.equals("boolean")) {
                    precision = 5;
                } else {
                    precision = field.getLength() + varcharPrecision;
                    if (precision == 0) {
                        precision = 1024;
                    }
                }

                if (precision > (MAX_PRECISION + varcharPrecision)) {
                    precision = MAX_PRECISION + varcharPrecision;
                }

                return typeFactory.createTypeWithNullability(typeFactory.createSqlType(typeName, precision), true);
            }
        } else {
            return typeFactory.createTypeWithNullability(typeFactory.createSqlType(typeName), true);
        }
    }

    private static SqlTypeName convertSfdcSqlToSqlType(FieldType field) {
        if (field.getValue().equalsIgnoreCase("string") || field.getValue().equalsIgnoreCase("boolean")
                || field.getValue().equalsIgnoreCase("base64") || field.getValue().equalsIgnoreCase("id")
                || field.getValue().equalsIgnoreCase("reference") || field.getValue().equalsIgnoreCase("textarea")
                || field.getValue().equalsIgnoreCase("phone") || field.getValue().equalsIgnoreCase("url")
                || field.getValue().equalsIgnoreCase("email") || field.getValue().equalsIgnoreCase("picklist")
                || field.getValue().equalsIgnoreCase("multipicklist")
                || field.getValue().equalsIgnoreCase("combobox") || field.getValue().equalsIgnoreCase("calculated")
                || field.getValue().equalsIgnoreCase("anytype")) {
            return SqlTypeName.VARCHAR;
        } else if (field.getValue().equalsIgnoreCase("int")) {
            return SqlTypeName.INTEGER;
        } else if (field.getValue().equalsIgnoreCase("double") || field.getValue().equalsIgnoreCase("currency")
                || field.getValue().equalsIgnoreCase("percent")) {
            return SqlTypeName.DOUBLE;
        } else if (field.getValue().equalsIgnoreCase("date")) {
            return SqlTypeName.DATE;
        } else if (field.getValue().equalsIgnoreCase("datetime")) {
            return SqlTypeName.TIMESTAMP;
        } else if (field.getValue().equalsIgnoreCase("time")) {
            return SqlTypeName.TIME;
        } else { // unknown
            return SqlTypeName.VARCHAR;
        }
    }
}

// End SfdcNameDirectory.java