2015-06-29 1 views
1

Моя задача - создать построитель журналов для jooq-подпрограмм. я начал прибегая к помощи вокруг и в конечном итоге с помощью этого: http://www.jooq.org/doc/latest/manual/sql-execution/execute-listeners/pretty logging in jooq

В данном примере автор использует доступный из коробки

DSL.using(configuration).renderInlined(ctx.routine()); 

Это выглядело многообещающим, но не было достаточно, потому что jooq не показал имена полей в подпрограммах, просто значения. Результат был трудно понять с помощью более крупных процедур. Я пробовал играть с другими возможностями, но безрезультатно ...

Я написал свой собственный форматор журналов, который даже работает. На данный момент :)

Итак, вот моя проблема: она работает только для результатов.

Почему? Потому что я могу получить доступ только к ctx.routine().getReturnValue(). ctx.routine().getInValues() защищен.

Итак, вот некоторые вопросы: почему getInValues() защищен? Можно ли его изменить на публику? Или, может быть, есть обходной путь для этого ...?

В качестве обходного решения я попытался использовать отражение, которое показывает еще одну проблему. getReturnValue() дает мне UDTRecord, у которого intoMap() метод возвращается Map<String, Object>. getInValuesMap<Parameter<?>, Field<?>>. Я понятия не имею, как работать с ним ... я решил не связываться с целой библиотекой и задать свои вопросы здесь :)

с нетерпением ждет ваших ответов

С наилучшими пожеланиями

редактировать : вставка первого черновика моего кода ниже. возможно, это поможет вам понять, чего я пытаюсь достичь.

import org.jooq.*; 
import org.jooq.impl.*; 

import java.util.Map; 

public class OutputLogBuilder 
{ 
    private final static String NEW_LINE = System.getProperty("line.separator"); 
    private final static String TAB = "\t"; 
    private final static String COL_RECORD_SEPARATOR = " --> "; 

    static String buildOutputLog(final ExecuteContext ctx) 
    { 
    StringBuilder sb = new StringBuilder(NEW_LINE); 
    handleUDTRecord(sb, ctx.routine().getReturnValue(), 0); 

    return sb.toString(); 
    } 

    private static void handleUDTRecord(final StringBuilder sb, final Object input, int depth) 
    { 
    UDTRecordImpl record = (UDTRecordImpl) input; 
    appendData(sb, record.getUDT().getName(), "", depth); 
    depth++; 

    for (Map.Entry<String, Object> entry : record.intoMap().entrySet()) { 
     String entryKey = entry.getKey(); 
     Object entryValue = entry.getValue(); 

     if (isArrayUDTRecord(entryValue)) { 
     handleArrayUDTRecord(sb, entryValue, depth); 
     } else if (isUDTRecord(entryValue)) { 
     handleUDTRecord(sb, entryValue, depth); 
     } else { 
     appendData(sb, entryKey, entryValue, depth); 
     } 
    } 
    } 

    private static boolean isArrayUDTRecord(final Object object) 
    { 
    return object instanceof ArrayRecordImpl; 
    } 

    private static boolean isUDTRecord(final Object object) 
    { 
    return object instanceof UDTRecordImpl; 
    } 

    private static void handleArrayUDTRecord(final StringBuilder sb, final Object input, int depth) 
    { 
    ArrayRecordImpl arrayRecord = (ArrayRecordImpl) input; 
    appendData(sb, arrayRecord.getName(), "", depth); 
    depth++; 

    for (Object arrayElement : arrayRecord.getList()) { 
     if (isArrayUDTRecord(arrayElement)) { 
     handleArrayUDTRecord(sb, arrayElement, depth); 
     } else if (isUDTRecord(arrayElement)) { 
     handleUDTRecord(sb, arrayElement, depth); 
     } else { 
     appendData(sb, input, "", depth); 
     } 
    } 
    } 

    private static void appendData(final StringBuilder sb, final Object key, final Object value, int depth) 
    { 
    for (int i = 0; i < depth; i++) { 
     sb.append(TAB); 
    } 
    sb.append(key + COL_RECORD_SEPARATOR + value); 
    sb.append(NEW_LINE); 
    } 
} 

edit2: С отражением мне удалось выяснить, как построить свой журнал с AbstractParam, UDTConstant и такие, но они защищены пакет ... ниже приведен пример фрагмента кода, чтобы проверить тип элементов

for (Map.Entry<Parameter<?>, Field<?>> entry : inValues.entrySet()) { 
    Parameter entryKey = entry.getKey(); 
    Field entryValue = entry.getValue(); 
    if(entryValue instanceof UDTConstant){ //access error 
    //do smth 
    } 
} 

поэтому, когда я проверить их тип я получаю
Caused by: java.lang.IllegalAccessError: tried to access class org.jooq.impl.UDTConstant from class org.jooq.impl.OutputLogBuilder
даже если (как вы можете видеть) я разместил свой код его в том же пакете ...
так снова - почему эти классы НЕ публичны? можно ли его изменить? есть ли какое-нибудь обходное решение?

+0

@ Lukas Eder - любые идеи? :) – WrRaThY

+0

[См. Мой ответ] (http://stackoverflow.com/a/31389243/521799). Хотя, ваш собственный ответ лучше, так что вы могли бы перенести эту часть своего вопроса и ответить на свой собственный вопрос, вот на Stack Overflow –

ответ

1

Что вы ищете, по существу, это недостающее особенность:

Routine API просто не достаточно сложные для того, что вы пытаетесь сделать. Любое обходное решение (например, использование рефлексии) или исправление исходных данных придется делать пока.

+0

thx для ответа. пс. мне кажется немного странным ответить на мой собственный вопрос, поэтому я просто принимаю ваш ответ :) – WrRaThY

+0

@WrRaThY: [Это не странно вообще) (https://blog.stackexchange.com/2011/07/its-ok -в-аск-ответ ваш собственный-вопросы /). Я делал это много раз сам, так что вперед! На самом деле, это даже лучше, чем редактирование вашего вопроса с частичным решением, потому что решение в вопросе необычно для переполнения стека –